Skip to content
ExponaBLOG
ENGINEERING CRAFT · DAY 003 / 100

Back-of-the-envelope estimation: lessons from production

Rough numbers prevent expensive architecture mistakes.

Expona Admin6 min read

Back-of-the-envelope estimation

I've watched brilliant architects spend weeks designing solutions for problems that don't exist at their current scale. I've also seen teams caught completely off-guard when their "small" feature suddenly needed to handle 10x the traffic they expected. The difference between these outcomes? One group did rough math early, and the other didn't. Back-of-the-envelope estimation is the practice of doing quick, order-of-magnitude calculations to validate your architecture decisions before you build them.

It's not about being precise. It's about being directionally correct—catching when you're off by a factor of 100 before you commit resources, budget, and team months to infrastructure you don't need, or worse, infrastructure that will collapse under load.

Why estimates matter before you build

Early in your career, estimation feels like a luxury. Once you've shipped a few systems that crumbled under unexpected load or a few that cost five times what they should have, it becomes non-negotiable.

I worked on a ride-hailing platform where the team assumed they'd handle "maybe 5,000 trips a day" in the first quarter. They built a single-threaded job processor and ran calculations on a spreadsheet, not during request time. Three months in, we hit 15,000 trips per day. The system didn't fail immediately, but margins got razor-thin. We spent two months refactoring the async pipeline, splitting the processor across workers, and moving heavy calculations to Kafka streams. That refactor cost more time and money than designing it right from day one would have.

Back-of-the-envelope estimation prevents this. It takes 20 minutes and a calculator. It catches scaling problems before they become crises.

1 million requests per day is roughly 12 per second

Let's start with the most common number you'll hear: daily volume. But raw daily figures don't tell you whether your database can handle the traffic. You need to convert to requests per second.

The math is straightforward:

typescript
const requestsPerDay = 1_000_000;
const secondsPerDay = 86_400;
const requestsPerSecond = requestsPerDay / secondsPerDay;

console.log(`${requestsPerSecond.toFixed(2)} RPS`); // ~11.57 RPS

That's around 12 requests per second. But here's where people get into trouble: they design for 12 RPS, deploy, and then traffic hits 15 RPS on day two. You're not done yet.

In an e-commerce platform I built, the product team estimated 500,000 orders per day. We did the math: that's about 5.8 RPS. Sounds manageable. But then Black Friday happened—volume went to 2 million orders in 24 hours. Suddenly we needed to handle 23 RPS, but our database connection pool was tuned for 10. The lessons were painful but valuable.

The key insight: your daily estimate is rarely a steady stream. Traffic clusters around business hours, flash sales, and external events.

Peak traffic is often 3–5x the average

This is the number that saves you. Peak traffic multiplier.

If you're averaging 12 RPS across a full day, but users wake up at 8 AM and access your system until 11 PM, your actual active window is maybe 15 hours, not 24. That alone pushes you to about 19 RPS during business hours. Add a product launch, a viral tweet, or a newsletter blast, and you're at 3–5x the average.

My rule of thumb:

  • B2B SaaS (steady, predictable): 2–3x multiplier
  • E-commerce (daily peaks, flash sales): 4–5x multiplier
  • Social media (trending moments): 5–10x multiplier, sometimes higher

Let's recalculate:

typescript
const averageRPS = 11.57;
const peakMultiplier = 5;
const peakRPS = averageRPS * peakMultiplier;

console.log(`Average: ${averageRPS.toFixed(2)} RPS`);
console.log(`Peak (5x): ${peakRPS.toFixed(2)} RPS`);
// Average: 11.57 RPS
// Peak (5x): 57.86 RPS

Now 58 RPS is what you need to provision for. Not 12. A PostgreSQL instance with proper tuning can handle 50–100 RPS comfortably. A poorly tuned one fails at 15. Your database connection pool, memory, and CPU need to accommodate peak, not average.

On the travel platform I worked on, we underestimated the checkout peak during holiday booking season. We assumed 2x multiplier. Reality was 6x. The checkout endpoint timed out repeatedly. We had to emergency-provision additional read replicas and implement aggressive caching, all while customers complained on social media. Lesson learned: ask your product team and check historical data before guessing.

Storage = items per day × size × retention

Storage estimation is usually overlooked until disk fills up at 3 AM and wakes up the on-call engineer.

The formula is simple but powerful:

typescript
const itemsPerDay = 1_000_000;
const bytesPerItem = 2_048; // 2 KB per order
const retentionDays = 365;

const totalBytes = itemsPerDay * bytesPerItem * retentionDays;
const totalGB = totalBytes / (1024 ** 3);

console.log(`Year 1 storage: ${totalGB.toFixed(2)} GB`);
// Year 1 storage: 730.30 GB

730 GB per year. Sounds manageable. But this is where specifics matter:

Is that 2 KB the raw item, or does it include indexes? Indexes typically add 20–50% overhead. Do you have replicas? A single primary plus one replica doubles your storage. What about backups? Most platforms keep daily backups for 30 days and weekly backups for a year. Suddenly your 730 GB becomes 5–6 TB.

For the CRM I built, we estimated 100 KB per customer record (including related contacts, interactions, attachments). With 50,000 new customers per day, 1-year retention, and a 3-node cluster with backups, we needed about 18 TB of raw disk. We budgeted for 30 TB to account for growth and safety margin. This number drove infrastructure decisions: we went with AWS RDS Multi-AZ instead of self-managed Postgres on EC2, because managing 30 TB across nodes becomes operational hell.

Keep a spreadsheet of these calculations. Revisit them quarterly. When actual numbers diverge from estimates, update your model.

Round aggressively — you need orders of magnitude

This is the permission you need to stop overthinking.

When estimating, rounding to the nearest order of magnitude is not just acceptable—it's the point. You're not budgeting down to the kilobyte or the millisecond. You're validating that your architecture can scale to the right ballpark.

Example: Is 2 KB per order accurate, or is it really 1.8 KB? It doesn't matter. Order of magnitude: thousands of bytes. Is traffic 11.57 RPS or 12 RPS? Again, doesn't matter. Order of magnitude: tens of RPS.

What does matter:

  • Are you off by 10x? That changes your architecture (single server vs. load-balanced cluster).
  • Are you off by 100x? That changes your tech choice (PostgreSQL vs. specialized analytics database).
  • Are you off by 1000x? That's a different business model entirely.

I estimate in round numbers on purpose. 1M requests, not 987,345. Peak 5x, not 4.7x. 2 KB per item, not 2,047 bytes. The false precision would make me feel rigorous but wouldn't make my design better. The rounded numbers, conversely, force me to think about whether I'm in the right ballpark. And that's the only question that matters at estimation time.

Common mistakes

Mistake 1: Confusing average and peak. You build for average, your system crashes on peak. Always design for peak. If peak is unknown, assume 5x.

Mistake 2: Forgetting the multiplier entirely. I see teams calculate 12 RPS and provision a database for 15 RPS, thinking they have headroom. Headroom is the difference between 12 RPS and 60 RPS (peak). Everything else is just bad math.

Mistake 3: Storage estimates that ignore overhead. Raw data size is one thing. Indexes, replicas, backups, and WAL logs triple or quadruple it. Don't omit them.

Mistake 4: Estimating once and forgetting. Estimates become stale. If you estimated six months ago and business doubled, your numbers are garbage. Revisit quarterly.

Mistake 5: Being too precise. "We need 47.3 RPS" is a sign you've overthought this. You need something in the range of 40–60 RPS. Round it and move on.

Key takeaways

  • Convert daily volume to RPS immediately. 1M per day ≈ 12 RPS. This is your baseline, not your target.
  • Multiply by peak factor (3–5x for most products). This is your real target. Design infrastructure to handle it.
  • Storage = daily items × size × retention × overhead multiplier (accounts for indexes, replicas, backups). Don't guess this; calculate it and update quarterly.
  • Round aggressively. You're checking orders of magnitude, not decimal places. If you're within a factor of 2, your estimate is good.
  • Do this math before architecture decisions. Spend 20 minutes with a calculator. Save your team weeks of refactoring.
  • Revisit estimates when business metrics change. Growth, new features, or shifted user behavior can invalidate your model fast.
ShareXLinkedInReddit

Found this useful? Support the writing.

Buy me a coffee
Written by
Expona Admin
Site administrator

Comments

Loading comments…

Leave a comment

Comments are reviewed before they appear. Be kind and stay on topic.

Related articles