Skip to content

Archive

Backend

36 articles
Web Development 01 Sep 2026 5 min read

Preventing SSRF in Backend Services That Fetch User-Supplied URLs

Features that fetch a URL supplied by a user appear in webhook testers, image importers, link previewers, document converters, and integration platforms. They also create a server-side request forgery (SSRF) boundary: an attacker can try to make the backend send requests to destinations the attacker cannot reach directly. A secure design needs more than a blacklist of suspicious strings. Understand the trust boundary The dangerous capability is not URL parsing itself. It is allowing untrusted input to influence a network connection made with the server’s network identity.

Web Development 01 Sep 2026 6 min read

Liveness and Readiness Health Checks for Backend Services

Health endpoints look simple, but their semantics directly affect how a production platform routes traffic and restarts applications. A poorly designed check can turn a temporary database slowdown into a restart loop or send requests to an instance that has not finished initializing. The most useful model separates two questions: Liveness: Is this process still capable of running? Readiness: Should this instance receive new traffic right now? Those questions sound similar, but they should usually have different answers and different failure behavior.

Web Development 01 Sep 2026 7 min read

Keyset Pagination in SQL for Fast, Stable APIs

Pagination looks simple until a table becomes large or new rows are inserted while a client is paging through results. LIMIT and OFFSET are easy to understand, but deep offsets can become expensive and changing data can make rows appear twice or disappear between requests. Keyset pagination, also called seek pagination, avoids those problems by asking for rows after a known position instead of asking the database to skip a number of rows.

Database 01 Sep 2026 4 min read

Keyset Pagination for Stable and Efficient Database Queries

Pagination looks straightforward with LIMIT and OFFSET, but deep offsets become increasingly expensive and can produce unstable results when rows are inserted or deleted between requests. Keyset pagination, also called seek pagination, uses the last seen sort key as the starting point for the next query. Why OFFSET degrades A typical query is: SELECT id, created_at, title FROM posts ORDER BY created_at DESC LIMIT 50 OFFSET 100000; The database still has to find and skip preceding rows before returning the page. There is also a correctness problem: if a new row is inserted at the front between requests, offsets shift and a user may see a duplicate or miss an item.

Web Development 01 Sep 2026 8 min read

Idempotency Keys for Safe API Retries

Retries are essential in distributed systems. Networks fail, clients time out, load balancers reset connections, and responses sometimes disappear after a server has already committed a write. The dangerous case is a retry of a non-idempotent operation. If a client sends POST /orders, times out, and sends the same request again, the server may create two orders even though the user intended one. An idempotency key gives the client a stable identifier for one logical operation. The server remembers the result associated with that key and can return the same result when the request is retried.

Go 01 Sep 2026 7 min read

Graceful HTTP Server Shutdown in Go

Stopping a web server with Ctrl+C looks harmless during development, but production deployments need a more careful shutdown process. If a process exits immediately, active HTTP requests can be interrupted, clients may receive connection errors, and in-flight work can be left unfinished. Go’s standard library already provides the pieces needed for a clean shutdown. The main tools are os/signal, context, and http.Server.Shutdown. This guide shows a practical pattern for shutting down an HTTP server when the process receives SIGINT or SIGTERM.

Go 01 Sep 2026 4 min read

Go Error Wrapping with errors.Is and errors.As

Errors often cross several layers of a Go application. A low-level function may know that a file is missing, while a higher-level function needs to add context about which operation failed. Go error wrapping lets you add that context without losing information callers need for reliable handling. Error strings are a fragile interface Do not make program logic depend on error wording. Adding a filename or changing punctuation can break string comparisons even when the underlying condition is unchanged. Prefer semantic checks:

Go 01 Sep 2026 8 min read

Go Context Timeouts and Request Cancellation

A Go HTTP handler can outlive the request that started it unless the work inside the handler pays attention to cancellation. That matters when a client disconnects, an upstream request takes too long, or a database query is no longer useful. Go solves this with context.Context. Every incoming *http.Request already has a context, and that context is canceled when the client connection closes, the request is canceled by HTTP/2, or the handler returns. You can also derive a shorter deadline for work that should not consume the entire request lifetime.

Go 01 Sep 2026 6 min read

Exponential Backoff with Jitter in Go

Retries can make distributed systems more resilient, but immediate retries can also make an outage worse. If thousands of clients retry at the same moment, a recovering dependency receives another synchronized burst of traffic before it has time to stabilize. A common solution is exponential backoff with jitter: increase the maximum delay after each failure, then randomize the actual wait. This article builds that pattern with Go’s standard library and shows where retry logic belongs—and where it does not.

Go 01 Sep 2026 4 min read

Coalesce Duplicate Work with Single-Flight Patterns in Go

Concurrent services often receive bursts of requests for the same expensive value: configuration, a database row, a rendered artifact, or a remote API response. A cache helps after the first request completes, but it does not stop ten simultaneous cache misses from doing the same work ten times. A single-flight pattern lets one caller perform the work while other callers wait for that result. The cache-miss stampede problem Without coordination, several callers can observe the same miss and all call the dependency. Single-flight changes that behavior so one request becomes the leader and later requests for the same key become followers.

Go 01 Sep 2026 7 min read

Bounded Concurrency in Go with a Worker Pool

Goroutines are cheap, but the resources they call are often not. Starting one goroutine for every item in a large batch can overwhelm a database connection pool, trigger API rate limits, exhaust file descriptors, or create avoidable memory pressure. Bounded concurrency solves this by allowing only a fixed number of operations to run at the same time. A worker pool is one of the simplest standard-library patterns for implementing that limit in Go.

Go 01 Sep 2026 6 min read

Atomic File Writes in Go: Prevent Partial and Corrupted Files

Writing a file with os.WriteFile is simple, but it is not always the safest choice for configuration files, generated metadata, caches, state files, or other data that must never be left half-written. If a process crashes or the machine loses power while a file is being replaced, readers may observe incomplete content. A common way to reduce this risk is an atomic file write: write the new content to a temporary file first, then replace the destination with a rename.