Problem says X → think Y

The searchable index of this domain. The left column is what the problem sounds like when someone describes it to you; the right column is the thing to think before you start typing.

63 of 63 rows
The problem saysThink
One endpoint is slow and nobody knows which part of itDo not guess — trace the request. A span per layer tells you whether the time is in your code, the pool, the query or a dependency.Tracing From the Backend's Side →
The same rows are read on nearly every requestCandidate for a cache — but first ask what happens when it is stale, and who invalidates it. A cache you cannot invalidate is a consistency bug you have not hit yet.Cache-Aside →
One request makes hundreds of small database round tripsN+1. Batch the loads or eager-load the relation; the fix is one query shaped for the access pattern, not a faster database.The N+1 Query Problem →
The client posted twice and you charged twiceIdempotency. A client-supplied key, stored with the result, so the second attempt returns the first outcome instead of repeating it.Idempotency Keys →
A third-party API got slow and your whole service got slow with itTimeout first, then circuit breaker. Without a timeout their outage becomes your outage, because your workers are all parked in their socket.Timeouts →
A dependency fails intermittently and the operation is safe to repeatRetry with exponential backoff and jitter, bounded attempts. Retries without jitter synchronise clients into a second wave.Backoff and Jitter →
Users upload large files and the request times out or the process balloonsThe bytes should not pass through your process. Presigned upload straight to object storage; your backend issues the URL and records the result.Presigned URLs →
The work takes longer than anyone will wait for a responseBackground job. Accept, persist the intent, return a handle the client can poll or subscribe to.Request or Background? →
Traffic arrives in bursts far above the steady rateA queue turns a burst into a backlog — a latency problem instead of an error. That is a trade, not a free win.Job Queues →
The queue depth is growing and never comes back downConsumers are slower than producers. Either add worker capacity or apply backpressure at the producer; adding queue capacity only delays the same conversation.Queue Backlog →
1000 concurrent requests, database pool of 20Requests are queueing for connections, not failing. Latency climbs first, errors arrive later when the acquire timeout fires.Connection Pools →
It worked on one instance and broke when you deployed twoShared state living in process memory — a counter, a lock, a session, a cache. Externalise it or accept it is per-instance.Stateless Services →
A user changed the id in the URL and saw someone else's dataObject-level authorization. Authentication proved who they are; nothing checked whether this row is theirs.Object-Level Authorization →
The response is enormous and gets slower as the table growsPagination, and cursor-based if the data changes underneath the reader. Also ask why the client needs every row at all.Pagination That Survives a Large Table →
A provider sends the same webhook three timesDuplicate delivery is the normal case, not the error case. Make the handler idempotent on the provider's event id.Webhook Idempotency →
A deploy breaks because the old version is still running against the new schemaExpand and contract. Every migration must be compatible with the version currently serving traffic, in both directions.Expand and Contract Migrations →
p50 is fine, p99 is terrible, and the CPU looks idleSomething is queueing — pool, event loop, worker set, a downstream lock. Idle CPU with rising tail latency is a waiting problem, not a compute problem.Why Is My API Slow? →
Latency stepped up at a specific minute and never came backSuspect the deploy first. Correlate the change point with releases, config changes and flag flips before reading any code.Deploys Are the First Suspect →
Memory grows monotonically until the process is killed and restartsSomething long-lived is holding references — an unbounded in-process cache, a growing array, listeners never removed.Memory Leaks in Backend Services →
A dependency recovered but your service stayed downRetry storm. Every client retried at once and re-broke it. Backoff, jitter and a breaker that stays open long enough to let recovery happen.Retry Storms →
Every request is slow, all at once, across unrelated endpointsA shared resource is saturated: the pool, the loop, the CPU, or one dependency that everything touches.Connection Pool Exhaustion →
A single CPU-heavy operation makes every concurrent request slowOn a single-threaded runtime you blocked the loop. The fix is to move the work off the loop, not to optimise the loop.Blocking the Event Loop →
One failing service takes down three that do not depend on itCascading failure through a shared resource — a thread pool, a connection pool, a gateway. Bulkheads isolate the blast radius.Cascading Failure →
A slow dependency consumed every worker, so healthy work could not runBulkhead. Give each dependency its own bounded concurrency so it can only exhaust its own share.Bulkheads →
A dependency is hard down and you keep calling it anywayCircuit breaker: fail fast while it is broken, probe occasionally, and decide what a degraded response looks like.Circuit Breakers →
Two requests read the same row, both updated it, one update vanishedLost update. Optimistic concurrency with a version column, or make the write atomic in the database rather than in your process.Optimistic Concurrency →
A counter or balance drifts from the truth under loadRead-modify-write in application code. Push the arithmetic into a single atomic statement the database serialises for you.Atomic Operations →
Two workers picked up the same job and both did itAt-least-once delivery is the default. The job must be idempotent, or claimed with a lock the queue actually enforces.Job Idempotency →
The database write succeeded and the event was never publishedDual write. Two systems, no shared transaction. The outbox pattern makes the event part of the same commit.The Dual Write Problem →
A transaction holds open while you call a payment providerNetwork calls do not belong inside a transaction — the row locks and the pooled connection are held for however long they take to answer.External Calls Inside a Transaction →
Deadlocks appear under concurrency and disappear when you retryTwo transactions taking the same locks in different orders. Fix the ordering; the retry is a mitigation, not the answer.Deadlocks in Application Code →
A cache key expires and a hundred requests all rebuild it at onceStampede. Coalesce the rebuild behind one worker, or serve the stale value while one refresh runs.Cache Stampede →
Different instances return different answers for the same cached readA local in-process cache with no invalidation channel. Either accept per-instance staleness deliberately or move it to a shared cache.Local vs Distributed Cache →
You added a cache and the hit rate is low but the bugs are realSome workloads should not be cached: highly personal, rarely reread, or cheap to compute. A cache with a low hit rate is pure added complexity.When Not to Cache →
The API returns the database row, and renaming a column broke a clientSchema leakage. A response model is a contract; the table is an implementation detail that must be free to change.Schema Leakage →
A 500 response contains a stack trace, a SQL fragment or a hostnameError boundary. Map internal errors to a safe external shape, log the detail with a correlation id the user can quote.Not Leaking Your Internals →
You have the user's complaint but cannot find their request in the logsCorrelation id, generated at the edge, propagated through every layer and job, returned to the client.Correlation Ids That Survive Every Hop →
Logs are human sentences you cannot filter or aggregateStructured logging. Fields, not prose — the value of a log line is what you can query it by six months later.Structured Logging →
The health check is green while every request failsIt is checking the process, not the service. Separate liveness from readiness, and decide deliberately which dependencies a readiness check includes.Health Checks: Startup, Readiness, Liveness →
Deploys drop in-flight requests and clients see connection resetsGraceful shutdown: stop accepting, drain in-flight work, close pools, exit — and make sure the orchestrator's grace period is longer than your drain.Graceful Shutdown →
One customer's query load degrades every other customerNoisy neighbour in a shared tenant. Per-tenant limits and isolation, decided at the data-access layer rather than hoped for.Multi-Tenancy →
A tenant filter is applied in most queries but not all of themTenant isolation must be structural — enforced in one place that queries cannot bypass, not repeated in every handler.Tenant Isolation →
A user string ends up inside a SQL statementParameterise. String interpolation into SQL is the vulnerability; an ORM does not make it safe if you still build the fragment by hand.SQL Injection →
Your backend fetches a URL the user suppliedSSRF. Your service can reach the metadata endpoint and the private network; the user's browser cannot. Allow-list, resolve, and re-check after redirects.SSRF — When the Backend Fetches a URL →
An API token turned up in a log line or an error reportSecrets in logs. Redact at the serialiser, not in review — anything that can be logged eventually will be.Secrets in Logs →
Config differs between environments and the failure appears only in productionValidate configuration at startup and fail loudly. A missing variable should stop the process, not surface as a null three hours later.Validate at Startup, Fail Loudly →
Tests pass, production breaks, and the difference is the databaseMocked persistence proves your mock. Integration tests against a real engine are what prove the query, the constraint and the migration.Test Against the Real Database →
Two services agreed on a contract in a document and disagreed in productionContract tests. The consumer's expectations, executed against the producer, in the producer's pipeline.Contract Tests Between Services →
Serialization shows up as the hot path in a CPU profilePayload size and shape are a CPU cost, not just a bandwidth cost. Return fewer fields before reaching for a faster serialiser.What Serialization Costs →
A caller hammers one endpoint and degrades it for everyone elseRate limiting, scoped to the identity that matters — key, tenant or IP — and returning a response that tells them when to come back.Rate Limiting →
Your rate limiter lets through double the limit at the window edgeA fixed window does that by construction. Sliding window or token bucket, and know which shape you actually promised.Rate Limit Algorithms →
Sessions vanish when a request lands on a different instanceSession state is in process memory. Move it to shared storage; sticky sessions are a workaround with its own failure mode.Where Sessions Live →
Auth runs after an expensive middleware, so anonymous traffic costs you moneyMiddleware order is a correctness and cost decision. Cheap rejections first; expensive work only for requests that earned it.Authenticate First, or Rate-Limit First? →
A role check passes but the user still should not see this particular recordRole-based access answers "may this kind of user do this kind of thing". It never answers "is this row theirs".Authentication vs Authorization →
Read traffic is the bottleneck and the primary is write-lightRead replicas — after deciding which reads tolerate replication lag and which must read their own writes.Read Replicas From the Application →
Autoscaling reacts long after users have already noticedCPU is a lagging signal for an IO-bound service. Scale on the queue or concurrency signal that actually leads the pain.Autoscaling a Backend →
A job failed 25 times and is still being retriedDead-letter queue with a retry limit, plus something that actually looks at the dead letters. An infinite retry hides a permanent failure.Dead-Letter Queues →
A search page shows data the database updated minutes agoThe index is a derived store kept in sync asynchronously. Decide the acceptable lag and make the sync recoverable.Keeping a Search Index in Sync →
A feature works but you cannot turn it off without a deployFeature flag. Separate deploying the code from enabling the behaviour, and give yourself an exit that does not need a release.Feature Flags: Rollout, Kill Switches and Debt →
An unbounded fan-out issues as many concurrent calls as there are itemsBound the concurrency. Promise.all over a thousand items is a thousand simultaneous dependency calls and a self-inflicted load test.Unbounded Concurrency →
An LLM agent can call your internal endpointsA tool call is a backend call. Same authorization, same limits, same audit trail — the prompt is not a security boundary.A Tool Call Is a Backend Call →
An agent loop calls a paid API until the bill is noticedBudgets and caps enforced server-side per run and per tenant, with the loop terminated by the backend rather than by the model changing its mind.Budgets, Deadlines and Step Limits →
You are about to split the monolith because the codebase feels bigSize is not a distribution problem. Modular boundaries inside one deployable get most of the benefit without turning function calls into network calls.The Modular Monolith →