Queues, Streams, Eventing
Exactly-once in production: impossibility proof, hybrid patterns, and real incidents
Stripe 2020: a bug in their internal queue consumer skipped the Idempotency-Key on retry, charging a small percentage of customers twice during a Q4 traffic spike. Refunded within 24 hours. The post-mortem: “exactly-once is harder than it looks; production correctness lives in consumer idempotency more than in broker guarantees.”
The Two Generals’ Problem: why exactly-once delivery is impossible
Two generals want to coordinate an attack at dawn. Their only communication is via messenger across enemy territory. Messengers may be captured. Can they agree?
Proof by contradiction: suppose a protocol exists. Consider the last message in the protocol that, if delivered, guarantees agreement. If we remove it, the protocol must still work — the sender already had certainty before sending that last message. By induction, the protocol works with zero messages — which is absurd, since they cannot coordinate without communicating.
The generalisation: no finite protocol over an unreliable channel can give both parties certainty that they share the same agreed fact.
Applied to queues: exactly-once delivery requires both producer and broker to know the message was delivered exactly once. Over an unreliable network, this is the Two Generals’ Problem. Exactly-once processing only requires one party — the consumer — to maintain a dedup log. One-sided certainty is achievable. Two-sided is not.
This asymmetry is why “effectively-once” is the real production target: at-least-once delivery from the broker, exactly-once processing enforced by the consumer.
The hybrid exactly-once pattern at scale
Pure Kafka exactly-once (within Kafka topics) does not extend to external systems. The production-grade pattern for a high-throughput payment processor:
- Kafka with idempotent producer (
enable.idempotence=true,acks=all). Eliminates producer-retry duplicates at ~3% cost. - Consumer at-least-once with
isolation.level=read_committed. Sees only committed records. - Per-message dedup table in Postgres:
BEGIN; INSERT INTO charges (msg_id, status) VALUES ('msg-7a3f', 'pending') ON CONFLICT DO NOTHING; -- if 0 rows inserted: already processed, skip COMMIT; -- call Stripe with Idempotency-Key=msg-7a3f UPDATE charges SET status='done', charge_id='ch_abc123' WHERE msg_id='msg-7a3f'; - Stripe Idempotency-Key derived from
msg_id. Stripe stores the first response for 24 hours; any retry returns the cached response.
Each layer is independently testable. The system survives crashes at any point with no duplicate charges. The dedup table also serves as an audit trail for financial reconciliation.
Observability for delivery semantics
Without metrics, you find out about duplicates from angry customers, not dashboards.
Per-broker metrics:
consumer_lag_messages— publisher offset minus committed offset. Sustained growth means consumers are falling behind.dlq_depthby source queue — alert at any non-zero value in production.dlq_age_seconds_p99— oldest message in DLQ; alert when >1 hour.
Per-consumer metrics:
dedup_check_hit_rate— how often the dedup INSERT is blocked by UNIQUE constraint. Should be near 0% in steady state. A spike indicates broker is redelivering aggressively — either a consumer-group rebalance, a bug causing early acks, or a broker issue.side_effect_duration_p99— if this exceeds your visibility timeout, you will see duplicates.retry_count_p99— sustained high values mean unhealthy consumers.
Distributed tracing: every message should carry a trace ID propagated from producer through consumer to any downstream service. Duplicate processing shows up as two spans with the same message trace ID — instantly distinguishable from legitimate distinct messages.
Real production failures
Stripe 2020: Internal queue consumer bug skipped Idempotency-Key on retry during Q4 spike. Small percentage of customers charged twice. Refund in 24 hours. Post-mortem result: hardened a linter rule that flags HTTP POST calls in consumer code paths that lack an Idempotency-Key header.
AWS SQS 2019: A region had a visibility-timeout race condition: consumers calling ChangeMessageVisibility while DeleteMessage was in-flight occasionally caused redelivery despite the delete completing. Fixed in next SDK release.
Stripe internal 2023: A hot DLQ accumulated 1M messages during a downstream incident. An operator ran redrive-all without rate limiting. Source queue received 1M messages simultaneously, overwhelming the consumer pool and triggering cascading throttling on the downstream payment API.
Slack 2022: A Kafka exactly-once stream pipeline had a transaction-coordinator bug during a broker rolling restart. The system delivered duplicates for 6 minutes until the rolling restart completed. Root cause: zombie producer sessions that had not been properly fenced.
The pattern in every incident: the correctness invariant failed in the consumer or the operational procedure, not in the broker guarantee itself. Broker guarantees are necessary but insufficient; end-to-end correctness requires consumer idempotency and operational discipline.
What is the actual reason Kafka exactly-once cannot extend natively to an external Postgres database?
In steady state, a consumer's dedup_check_hit_rate suddenly spikes from 0.05% to 8% for 10 minutes outside a deploy window. What is the most likely cause?
- 01State the Two Generals' Problem and explain the asymmetry that makes exactly-once processing achievable.
- 02What three layers compose the hybrid exactly-once pattern for a payment processor?
- 03What does a sustained dedup_hit_rate spike above 1% outside deploy windows indicate?
The Two Generals’ Problem proves that no finite protocol over an unreliable channel can give both sides certainty of agreement — this is why exactly-once delivery is impossible. Production systems achieve effectively-once through defence in depth: Kafka idempotent producer (~3% cost) eliminates producer-retry duplicates at the broker; consumer-side DB dedup with ON CONFLICT DO NOTHING eliminates Leg 3 duplicates atomically; Stripe Idempotency-Key eliminates cross-system duplicates at the payment API. Every real incident — Stripe 2020, SQS 2019, Slack 2022 — confirms the same pattern: correctness fails in the consumer or in operational procedure, not in the broker. Monitor dedup_hit_rate near zero in steady state; a sustained spike outside deploys means consumer instability, not a dedup failure.
appears again in202
- Why GraphQL gets N+1junior
- DataLoader mechanics: tick-boundary batchingmiddle
- Batch function contracts: ordering, shapes, errorsmiddle
- Federation and lookahead: batching beyond DataLoadermiddle
- Query complexity defences: depth, cost, persisted queriesmiddle
- Senior GraphQL API: scheduling contract, tenant isolation, observabilitysenior
- Why idempotency: making retries safejunior
- Server-side state machine: four states of an idempotency keymiddle
- Outbox and inbox: effectively-once across the dual-write boundarymiddle
- Concurrency and cache architecture for idempotency at scalesenior
- Observability, production failures, and global-scale designsenior
- The event loop: one thread, three queuesjunior
- Tasks, microtasks, and scheduler.yield()middle
- Microtask starvation, Long Tasks, and LoAFsenior
- Node.js event loop: phases, nextTick, and loop lagsenior
- React, Vue, and INP observability in productionsenior
- The render pipeline: six stages from bytes to pixelsjunior
- Stage costs and the renderer process modelmiddle
- Invalidation, dirty bits, and containmiddle
- Compositor layers: promotion, overlap, and GPU memorymiddle
- DevTools flame strip and the frame lifecyclemiddle
- Layout thrash: forced synchronous layoutsenior
- BeginMainFrame, compositor-driven animations, and GPU memorysenior
- Production observability: LoAF, INP, and the full attack surfacesenior
- What V8 is and why performance varies 100×junior
- V8''''s four-tier JIT pipeline and profile-guided tieringmiddle
- Hidden classes, transition trees, and memory layoutmiddle
- Inline caches, IC states, and deoptimizationmiddle
- Orinoco GC: parallel scavenger, concurrent marking, and write barriersmiddle
- TurboFan''''s speculative engine and the deopt-loop trapsenior
- V8 in production: isolates, pointer compression, and real failuressenior
- What workers are and why they existjunior
- Web worker mechanics: dedicated, shared, and OffscreenCanvasmiddle
- Structured clone and transferablesmiddle
- Service worker lifecycle and cache strategiesmiddle
- SharedArrayBuffer, Atomics, and cross-origin isolationsenior
- Service worker edge cases: version skew, durability, and navigation trapssenior
- Worker pools, Comlink, and production observabilitysenior
- What the reconciler does: render vs commitjunior
- The fiber object and the double-buffer treemiddle
- Render phase purity and commit phase sub-stepsmiddle
- Reconciliation: diffing heuristics and the key trapmiddle
- Priority lanes, time-slicing, and useTransitionmiddle
- Bailout, memoisation, and tearingsenior
- React Profiler, the Compiler, and production observabilitysenior
- Rendering strategies: SSG, SSR, ISR, streaming, and hydrationjunior
- SSG, SSR, ISR, streaming, and RSC — how each worksmiddle
- Hydration cost: selective, progressive, islands, resumabilitymiddle
- Hydration mismatch: causes, detection, and the determinism rulesenior
- RSC, per-route strategy, and production observabilitysenior
- Core Web Vitals: what LCP, INP, and CLS measurejunior
- CLS: why layout shifts happen and how to stop themmiddle
- Metric tradeoffs, RUM attribution, and the CI+field loopsenior
- The full picture: URL to LCP to INP as a relay racejunior
- Eight layers traced: from the service worker to the second navigationmiddle
- Five canonical breaks: where production reliably diessenior
- The three-track method: reading traces and building a monitored systemsenior
- What is a cache stampede and why it makes things worsejunior
- Lock and single-flight: bounding concurrent rebuildsmiddle
- XFetch: coordination-free probabilistic early expirationmiddle
- Stale-while-revalidate and CDN request coalescingmiddle
- Detecting stampedes and designing TTL for productionmiddle
- Metastable failure, fencing tokens, and production postmortemssenior
- What a relation is: tables, rows, keys, and constraintsjunior
- Constraints, keys, and Postgres data typesmiddle
- Normal forms, denormalization, and why schemas stickmiddle
- JSONB, arrays, and when a side table winsmiddle
- Heap storage, TOAST, and column alignmentsenior
- Schema integrity: deferral, versioning, and production failure modessenior
- Relational vs document, wide-column, graph, and key-valuesenior
- Index-only scans, the Visibility Map, and INCLUDEsenior
- Production failure modes and the index audit playbooksenior
- pg_statistic, ANALYZE, and production observabilitymiddle
- Production failure modes and plan stabilitysenior
- MVCC: why readers and writers never wait for each otherjunior
- Row versions and snapshots: the on-disk mechanicsmiddle
- HOT updates and isolation levels: what you gain and what you paymiddle
- Vacuum and bloat: keeping the storage tax boundedmiddle
- CLOG, XID wraparound, and MultiXact: deep visibility internalssenior
- SSI internals and production autovacuum tuningsenior
- Real-world MVCC failures, deployment patterns, and distributed snapshotssenior
- Connection pools: amortising the cost of a Postgres backendjunior
- PgBouncer session, transaction, and statement modesmiddle
- Pool sizing: the (cores × 2) + spindles formula and the two-layer stackmiddle
- Pool exhaustion and idle-in-transaction: the 3 AM failure modemiddle
- Migrating to transaction mode: rollout playbook and PgBouncer 1.21 prepared statementsmiddle
- The Postgres process model and why raising max_connections degrades throughputsenior
- Pooler landscape 2026, serverless connection storms, and the full failure-mode taxonomysenior
- What a schema migration is and why it replaces ad-hoc DDLjunior
- ADD COLUMN: instant in PG 11+ vs rewrite in older Postgresjunior
- The lock-queue failure mode: why instant DDL can freeze the databasemiddle
- Safe DDL patterns: NOT VALID, CONCURRENTLY, and unsafe-op fixesmiddle
- Expand-contract: zero-downtime for breaking schema changesmiddle
- Advisory locks, migration tools, and deploy coordinationsenior
- Migration failure taxonomy and production disciplinesenior
- Why sharding exists: the single-Postgres ceilingjunior
- Shard-key selection: hash, range, list, and directory strategiesmiddle
- Partitioning vs sharding: same word, two different thingsmiddle
- Co-location and Citus: the invariant that makes sharding usablemiddle
- The hot-shard failure mode: detection, isolation, and durable policymiddle
- Schema-based sharding and multi-tenancy alternativessenior
- Online resharding, 2PC, and the operational cost of shardingsenior
- The seven acts: from CREATE TABLE to Citusjunior
- Acts 1–3 in depth: schema, indexes, and planner statisticsmiddle
- Acts 4–6 in depth: MVCC bloat, connection pooling, and safe migrationsmiddle
- Act 7 in depth: sharding, co-location, and the seven-tier tradeoff cascademiddle
- Observability, anti-patterns, and production triagesenior
- Raft roles, terms, and why majority quorums prevent split brainjunior
- How Raft replicates a log entry and decides it is safe to commitmiddle
- Raft leader election: timeouts, voting rules, and the four safety propertiesmiddle
- Raft in the real world: partitions, slow disks, and client routingmiddle
- Raft extensions: pre-vote, learners, snapshots, and linearizable readssenior
- Raft in production: membership changes, Multi-Raft, and observabilitysenior
- Where data fetching happens — and why it decides LCPjunior
- Fetch waterfalls — diagnosis and the Promise.all curemiddle
- React Server Components and Suspense streamingmiddle
- Client-side cache: TanStack Query, SWR, and stale-while-revalidatemiddle
- LCP, prefetch, and race conditions in interactive fetchingmiddle
- Senior internals: RSC payload, caching layers, and production failure modessenior
- The IP envelopejunior
- Reading the IP headermiddle
- The three-way handshakejunior
- Sequence numbers and connection statemiddle
- DNS: what it does and why it existsjunior
- The resolver walk: referrals, record types, and gluemiddle
- TTL, caching, and DNS propagationmiddle
- What TLS does and why it existsjunior
- The 1-RTT handshake: key shares and ECDHEmiddle
- Session resumption and 0-RTTmiddle
- Key schedule, SNI, ALPN, and extensionssenior
- 0-RTT defenses, ECH, hybrid PQ, and production TLSsenior
- WebSocket: the HTTP upgrade handshakejunior
- WebSocket frame format: opcodes, masking, fragmentationmiddle
- WebSocket backpressure: when clients can''''t keep upmiddle
- Reconnection: jittered backoff, thundering herd, message resumptionsenior
- WebSocket at scale: HTTP/2 multiplexing, permessage-deflate, C10Msenior
- WebSocket in production: proxies, security, and distributed architecturesenior
- What reverse proxies dojunior
- Health checks, connection draining, and slow startmiddle
- Session affinity, consistent hashing, and the right fixmiddle
- Retry storms, circuit breakers, and load sheddingsenior
- Resilient LB architecture: anycast, zone-aware routing, and observabilitysenior
- Why QUIC and not TCP+TLSjunior
- Connection IDs and network migrationmiddle
- 0-RTT resumption and packet encryptionsenior
- DDoS: what it is and why it worksjunior
- Amplification attacks and state exhaustionmiddle
- Rate limiting: algorithms and architecturemiddle
- WAFs, firewalls, mTLS, and HSTSmiddle
- DNS cache poisoning and BGP hijackingsenior
- Defense-in-depth architecture and attack economicssenior
- The twelve layers: one URL, seven actorsjunior
- DNS, TCP, TLS in sequence: where the milliseconds gomiddle
- Proxy intercepts and security gates: rate limiters, WAF, mTLSmiddle
- Alternate paths: QUIC 0-RTT, WebSocket upgrade, connection migrationmiddle
- Observability: distributed traces, USE/RED, and samplingsenior
- Resilience: cascading retries, circuit breakers, and error budgetssenior
- What the three signals are: logs, metrics, and tracesjunior
- Why structured logs exist: the diary vs the spreadsheetjunior
- The production log schema: fields every line must carrymiddle
- PII redaction and log injectionsenior
- OTel Logs Data Model and audit logs as a subsystemsenior
- What is OpenTelemetry: API, SDK, Collector, OTLPjunior
- OTel signals, Semantic Conventions, and the OTLP wire formatmiddle
- The OTel Collector: receivers, processors, exporters, and deployment patternsmiddle
- Vendor neutrality, eBPF instrumentation, the Operator, and browser/serverless OTelsenior
- Operating the OTel Collector: reliability, version skew, failure modes, and governancesenior
- SLI, SLO, and the error budget: reliability by the numbersjunior
- Error budget policy, latency SLOs, and composite journeysmiddle
- Production SLO failures, self-observability, security, and the big picturesenior
- What is trace propagation and why broken propagation is worse than nonejunior
- traceparent and tracestate: the W3C header format in fullmiddle
- Baggage and async boundaries: carrying context across queues and callbacksmiddle
- Async context per language, service mesh, B3 migration, and securitysenior
- Production propagation failures, span links, and platform designsenior
- The debugging funnel: SLO → RED → trace → profilejunior
- OTel architecture: one SDK, four signals, one wire formatmiddle
- The incident loop: from pager to postmortem to preventionmiddle
- Scale, security, and the ROI of observable systemssenior
- Cache lines, struct layout, and false sharingmiddle
- SIMD, SoA vs AoS, and memory bandwidthmiddle
- Cache-oblivious algorithms, PGO, and production failuressenior
- GC in production: observability, security, edge cases, and fleet governancesenior
- Batching: amortize fixed cost per operationjunior
- The batching window: size and wait timemiddle
- Batching in Kafka and Postgresmiddle
- io_uring and observability of batchingmiddle
- From Nagle to io_uring: evolution of batchingmiddle
- Backpressure, failure isolation, and batch security in productionsenior
- CI enforcement and RUM: making budgets stickmiddle
- V8 JIT pipeline, HTTP priorities, and bundle securitysenior
- The performance loop: discipline, not a projectjunior
- Classify and fix: matching bottleneck families to remediesmiddle
- Observability stack and CI gates: catching regressions before they shipmiddle
- Incident to enforcement: SLO burn to verified fix in 35 minutesmiddle
- Culture, economics, and org-scale performancesenior
- What OAuth is and why passwords are not the answerjunior
- Authorization code flow with PKCEmiddle
- ID token validation and JWKS cache managementmiddle
- Refresh token rotation and scope-based least privilegemiddle
- Sender-constrained tokens: DPoP and mTLSsenior
- OAuth in production: audience attacks, observability, and real failuressenior