Read-Scale API
A read-optimized API tier using CDN edge caching, PostgreSQL read replicas, PgBouncer connection pooling, and Redis cache-aside. Handles read:write ratios of 10:1 or higher at 50k–5M DAU without sharding the primary database.
Description
The read-scale API composition addresses the most common scaling bottleneck in web applications: read pressure on a single PostgreSQL primary. Rather than jumping to horizontal sharding, this architecture extracts read capacity through three complementary layers: CDN caching for static and cache-friendly responses, Redis for computed results with sub-millisecond latency, and PostgreSQL read replicas for queries that require consistent relational access.
PgBouncer in transaction-mode pooling is the highest-leverage addition: 100 app instances holding 5 connections each map to 50 real PostgreSQL connections, reducing connection overhead by 90% while preserving query semantics.
Read replicas introduce replication lag: typically 10–500ms but up to minutes under write pressure. Application routing must accept eventual consistency on read paths. Writes always go to the primary. Reads from replicas must tolerate stale data; critical reads (after a write in the same request) must be routed to the primary.
Use Cases
- ·Consumer APIs with high read:write ratio (10:1 or greater)
- ·Content platforms where most requests are GETs
- ·B2C SaaS with 50k–5M DAU
- ·Read-heavy analytics endpoints serving dashboards
- ·APIs with expensive computed results that can be cached
Scale Profile
Entry Point
10k DAU with 500 RPS: monolith with single database is near ceiling
Sweet Spot
50k–2M DAU, 1k–30k RPS on read paths
Scaling Ceiling
~5M DAU or 50k RPS: replica lag becomes noticeable; write throughput on primary becomes bottleneck
Typical RPS
1k–30k RPS
Architecture Nodes (9)
Web browsers, mobile apps, and API consumers.
Edge caching layer. Serves static assets and cache-controlled API responses from edge POPs. Reduces origin load by 60–80% for public endpoints.
Layer-4/7 load balancer distributing traffic across API service instances. Health-checks each instance every 10s.
Stateless application servers. Routes reads to replica pool via PgBouncer. Routes writes to primary. All instances are identical: horizontal scale by adding instances.
Connection pooler in transaction mode. Multiplexes N*M application connections to a bounded real connection pool. Reduces PostgreSQL connection overhead by 80–95% under high concurrency.
Write-authoritative primary. Handles all INSERT/UPDATE/DELETE. Streams WAL to read replicas via streaming replication. Max write throughput: ~5k TPS for OLTP workloads.
Streaming replication replica. Handles read-only queries. Replication lag: 10–500ms typical, up to minutes under sustained write load.
Second read replica for read capacity and availability. Also serves as promotion candidate if primary fails.
Cache-aside store for expensive computed results, session data, and rate limiting. TTL-controlled. Cache key includes query parameters hash. Hit rate target: 85%+ for sustained read workloads.
Dependencies (10)
5 critical path edges. Failure on these directly degrades user-facing requests.
HTTPS requests
All requests first hit CDN edge. Cache HIT returns response immediately. Cache MISS passes through to origin.
Timeout: 5s
Cache miss passthrough
CDN forwards uncached requests to the origin load balancer. Cache-Control headers from the API drive CDN TTLs.
Timeout: 30s
Routed requests
Round-robin or least-connections distribution across API instances. Connection draining on deploy.
Timeout: 30s
Cache lookup / write
Cache-aside: check Redis first, populate on miss. GET requests check cache before hitting database. Cache invalidated on write.
Timeout: 100ms
All database queries
App never connects to PostgreSQL directly. All connections go through PgBouncer. Read queries routed to replica pool; writes to primary.
Timeout: 5s
Write queries
INSERT/UPDATE/DELETE and critical reads (read-your-writes) routed to primary only.
Timeout: 5s
Read queries
SELECT queries for non-critical read paths distributed across replica pool.
Timeout: 5s
Read queries
SELECT queries for non-critical read paths distributed across replica pool.
Timeout: 5s
WAL streaming
PostgreSQL streaming replication. Asynchronous by default: committed writes become visible on replicas after lag period.
WAL streaming
PostgreSQL streaming replication to second replica.
Failure Propagation
How a failure in one component cascades through the system. Each path documents the mechanism and the mitigation that breaks the chain.
Mechanism
Primary failure takes down write path entirely. Read path continues on replicas if PgBouncer is configured for read-only fallback. Promotion of replica takes 30–120 seconds with manual failover; automated failover (Patroni/pgauto) reduces to 15–30s.
Mitigation
Deploy Patroni or repmgr for automated failover. Configure PgBouncer to route reads-only during promotion. Alert on replication slot lag before primary fails.
Mechanism
Single PgBouncer instance is SPOF. If it crashes, all database connectivity is lost. App requests fail immediately.
Mitigation
Run PgBouncer as a sidecar per app instance or deploy 2 PgBouncer instances with connection-level failover.
Mechanism
Redis restart or eviction clears hot key space. All application instances simultaneously miss cache and issue database reads. PostgreSQL connection pool saturates in seconds.
Mitigation
Implement probabilistic early expiration (PER) to avoid simultaneous expiry. Use Redis Sentinel or Cluster for HA. Stagger cache TTLs with jitter.
Mechanism
High write load causes replica lag to exceed application tolerance. Reads from replica return stale data. Depending on domain (payments, inventory), this causes correctness issues.
Mitigation
Monitor replication lag continuously. Route sensitive read paths (balance checks, inventory) to primary. Alert and route all reads to primary when lag exceeds threshold (e.g. 500ms).
Scaling Transitions
Inflection points where this architecture begins to degrade and what the recommended evolution looks like.
Write throughput saturates primary. WAL generation causes replica lag spikes. VACUUM contention on high-update tables.
Recommended Action
Evaluate write patterns: if write load concentrates on a few tables, vertical scale the primary. If distributed, introduce table partitioning. Reserve horizontal sharding for verified write saturation.
Single Redis instance hot-spot on cache keys for popular entities. Memory pressure causes eviction of warm keys, raising DB load.
Recommended Action
Migrate to Redis Cluster with consistent hashing. Shard hot keyspaces across nodes.
Patterns Applied
Architectural Notes
- ·PgBouncer transaction-mode pooling is incompatible with prepared statements. Migrate to simple query protocol or use session-mode pooling at the cost of lower multiplexing efficiency.
- ·Replica lag is the most common operational surprise: monitor pg_stat_replication.replay_lag in Prometheus. Alert before it affects reads.
- ·CDN Cache-Control headers are the highest-leverage latency optimization. For unauthenticated endpoints, even a 5-second CDN TTL eliminates most origin traffic.
- ·Do not route writes through a replica by mistake: ORMs in read-write routing mode will silently succeed if the read flag is not set per query.
Confidence
StrongStandard read-scaling composition documented by PostgreSQL, GitHub, Shopify, and widely deployed at 10k–5M DAU scale.