Skip to main content

Posts

Showing posts with the label System Design

Cursor vs Offset Pagination: Optimizing Large Data Retrieval in REST APIs

  When a production database scales, few architectural choices cause as much silent degradation as standard   OFFSET   and   LIMIT   pagination. An endpoint that returns data in 20 milliseconds during testing can easily spike to multi-second response times in production when users navigate deep into a dataset. This latency spike, known as the deep pagination performance problem, is a direct result of how relational database engines execute offset commands. Fixing this requires shifting the API architecture from offset-based retrieval to keyset (cursor) pagination. The Mechanics of Deep Pagination Performance Degradation To understand why a REST API fails under deep pagination, you must examine the database execution plan. Relational databases like PostgreSQL and MySQL do not maintain a physical index of row offsets. When an API executes a query like  SELECT * FROM transactions ORDER BY created_at DESC LIMIT 50 OFFSET 500000; , the database engine cannot mat...

Redis Caching Patterns: Implementing Probabilistic Early Expiration (Jitter) to Stop Thundering Herds

  The Hook It starts with a single alerting pixel. Your database CPU spikes from 15% to 100% in less than a second. Latency alarms scream, and the connection pool exhausts immediately. The application isn't just slow; it’s down. The culprit? A single, highly accessed cache key (like a configuration blob or a homepage feed) expired. At $t=0$, the key existed. At $t+1ms$, it didn't. In that millisecond window, 5,000 incoming requests checked Redis, found nothing, and simultaneously hammered your primary database to recompute the same dataset. This is the  Thundering Herd  problem (also known as Cache Stampede), and standard TTLs are not enough to prevent it. The Why: Anatomy of a Stampede To solve this, we must understand the race condition. In a high-throughput system, a cache miss is expensive. Synchronization Gap:  When a key expires physically in Redis (TTL hits 0), it vanishes atomically. Concurrent Reads:  If your throughput is 10k RPS, and your database que...