Plate III
Journal
Journal
Working notes, written while the problem was still fresh.
14 entries
RSS feed- 001
Transactional outbox pattern: events that never go missing
Write to the database, then publish to Kafka, and one of them will eventually fail. How an outbox table makes the write and the event a single commit.
Distributed SystemsPostgreSQLReliabilityBackend - 002
Postgres as a job queue with SELECT FOR UPDATE SKIP LOCKED
You do not need a second system for background jobs. How SKIP LOCKED turns a table into a queue, and the details that decide whether it holds up.
PostgreSQLDatabasesBackendQueues - 003
PostgreSQL composite indexes: which column goes first
A multicolumn B-tree sorts by its first column, then its second. Why (a, b) and (b, a) are different indexes, and the rule that decides the order.
PostgreSQLDatabasesIndexingPerformance - 004
Kafka consumer lag: the only metric that tells you the truth
Throughput says how fast you are. Lag says whether you are keeping up. Why lag climbs, why adding consumers stops helping, and why rebalances make it worse.
KafkaMessagingDistributed SystemsBackend - 005
Database connection pool sizing: a pool is a queue with a depth
Every request waits in line for a connection. Little's law says how long the line is, why a bigger pool makes it slower, and how exhaustion cascades.
PostgreSQLBackendPerformanceReliability - 006
Clock skew: why timestamps cannot order events across servers
Two servers never agree on the time, so the one running behind overwrites the one ahead. What each clock is for, and what to sequence with instead.
Distributed SystemsBackendReliabilityTimekeeping - 007
Backpressure: when the consumer is slower than the producer
An unbounded buffer does not fix a speed mismatch, it postpones the crash. Bounded queues, blocking sends and early rejection, and where each one belongs.
BackendDistributed SystemsReliabilityPerformance - 008
Fixed window vs sliding window vs token bucket rate limiting
A 100 per minute counter will pass 200 requests in two seconds at the window boundary. What a sliding window and a token bucket cost, and which to ship.
Rate LimitingRedisAPI DesignBackend - 009
Idempotency keys: how to stop a retry double charging
A timeout never tells you whether the write landed. How an idempotency key settles it, and why the key has to commit in the same transaction as the work.
API DesignIdempotencyReliabilityBackend - 010
UUID primary keys and write amplification in PostgreSQL
A UUIDv4 primary key scatters every insert across the B-tree, turning one logical write into several physical ones. The mechanism, and when it matters.
PostgreSQLDatabasesUUIDPerformance - 011
Retry storms: exponential backoff, jitter and retry budgets
How synchronised retry waves form, why exponential backoff alone does not prevent them, and what a retry budget buys you that a retry count cannot.
Distributed SystemsReliabilityBackendRetries - 012
Keyset pagination vs OFFSET in PostgreSQL
OFFSET reads and discards every row it skips, and silently duplicates records when data shifts. Keyset pagination fixes both, at a price worth knowing.
PostgreSQLDatabasesAPI DesignPagination - 013
Deadline propagation: why chained timeouts add up
A timeout is a per-hop constant. A deadline is a budget the whole request shares. Why a chain of three-second timeouts lets a request run for nine.
Distributed SystemsBackendReliabilityTimeouts - 014
Build a REST API in Rust with Axum, SQLx and PostgreSQL
A step-by-step guide to building a type-safe REST API in Rust using Axum for the web layer and SQLx for database access. Covers project setup, connection pooling, and handlers.
RustBackendAPIAxum