Case 5
Back-of-the-Envelope Estimation
Ballot write spikes, results read QPS, and why tallies must be pre-aggregated.
Order-of-magnitude checks catch designs that cannot work. Adjust assumptions for your interview scope — exact numbers matter less than which component becomes the bottleneck.
Assume national election: 100M eligible voters, 70% turnout = 70M ballots, 80% cast in final 4 hours, ballot row 500 B, results page polled every 5s by 10M viewers.
Write traffic
- Ballots in 4 hours: 56M / 14,400s ≈ 3,900 ballots/s sustained in peak window.
- Spike at poll close if everyone waits: 70M in 10 min ≈ 116,000/s — must queue or stagger; edge rate limiting essential.
- Append-only INSERT — no UPDATE contention; partition by election_id.
Read traffic
- Results page: 10M users / 5s refresh ≈ 2M reads/s — served from Redis/materialized counts, never COUNT(*) on ballot table.
- Eligibility check: 70M once per voter ≈ 19,400/s if spread over 1 hour before peak.
Storage
- Ballots: 70M × 500 B ≈ 35 GB — trivial for Postgres; audit log retention is the policy driver.
- Aggregator state: 500 choices × 8 B count ≈ 4 KB — fits in memory; Redis replica for HA.
Network & caching
- Ballot POST ~1 KB request × 116k/s spike ≈ 116 MB/s ingress — API gateway + WAF at edge.
- Results JSON ~2 KB × 2M/s ≈ 4 GB/s egress at peak — CDN cache results page or aggressive edge caching.
- Cache warming: precompute totals on each ballot event; read path is O(1) per choice_id.
QPSappend-onlyRedisaggregatorpeak traffic