Loading learning content...
In the heat of a system design interview—or during an urgent production incident—you don't have time to derive formulas from first principles. You need instant recall of key numbers and equations that let you reason quickly about systems.
This page is your reference toolkit. It consolidates everything we've covered into quick-reference formulas, provides the essential numbers every system designer should memorize, highlights common estimation mistakes, and offers practice problems to build your intuition.
Think of this as your mental cheat sheet—not for memorizing by rote, but for internalizing the patterns that experienced engineers use instinctively. After working through this material and practicing, these estimations will become second nature.
By the end of this page, you will have: (1) A quick-reference formula sheet for all estimation types, (2) Essential numbers to memorize, (3) Awareness of the most common estimation pitfalls, (4) Practice problems with worked solutions, (5) Confidence to estimate any system rapidly.
Here are all the core formulas you need, organized by estimation type:
Traffic Estimation Formulas:
123456789101112131415
TRAFFIC ESTIMATION FORMULAS============================ Daily Requests = DAU × Actions/User × Requests/Action Average RPS = Daily Requests / 86,400 Peak RPS = Average RPS × Peak Multiplier (typically 2-5x) Concurrent Users ≈ DAU × 0.05 to 0.15 (5-15%) Read:Write Ratio = Read Requests / Write Requests Write RPS = Total RPS / (1 + Read:Write Ratio)Read RPS = Total RPS - Write RPSStorage Estimation Formulas:
1234567891011121314
STORAGE ESTIMATION FORMULAS============================ Raw Storage = Objects/Day × Size/Object × Retention Days Production Storage = Raw × Replication (3x) × Overhead (1.5x) Annual Storage = Daily New Storage × 365 5-Year Storage = Year1 × (1 + Growth Rate)^5 + Cumulative Index Overhead = Raw Data × 0.2 to 0.5 (20-50%) Compression Savings = Original × 0.7 to 0.9 (30-10% of original)Bandwidth Estimation Formulas:
1234567891011121314
BANDWIDTH ESTIMATION FORMULAS============================= Bandwidth (bytes/sec) = RPS × Response Size (bytes) Bandwidth (Gbps) = (bytes/sec × 8) / 1,000,000,000 Daily Data = RPS × Response Size × 86,400 Egress = Total Bandwidth - Ingress Origin Bandwidth = Total × (1 - CDN Cache Hit Ratio) Monthly Egress Cost = GB × Rate (tiered pricing)Server Estimation Formulas:
1234567891011121314151617
SERVER ESTIMATION FORMULAS=========================== Base Servers = Peak RPS / RPS per Server Multi-AZ Servers = Base × (AZs / (AZs - 1)) # For N AZs, survive 1 failure With Deployment = Multi-AZ × 1.15 (15% overhead) Production Total = With Deployment × 1.2 (20% spike headroom) Little's Law: L = λ × W L = concurrent requests λ = arrival rate (RPS) W = average latency (seconds) RPS = Concurrent Connections / Average LatencyCertain numbers appear so frequently in system design that having them memorized accelerates every estimation. Here's your essential list:
Time Constants:
| Period | Seconds | Useful For |
|---|---|---|
| 1 minute | 60 | Short-term rates |
| 1 hour | 3,600 | Hourly metrics |
| 1 day | 86,400 ≈ 100,000 | Round to 100K for easy math |
| 1 month | 2.5 million | Monthly volumes |
| 1 year | 31.5 million | Annual volumes |
| 1 million seconds | ~11.5 days | Sanity check |
| 1 billion seconds | ~31.7 years | Perspective |
Storage and Bandwidth Units:
| Unit | Bytes | Context |
|---|---|---|
| 1 KB | 1,000 | Small JSON, text messages |
| 1 MB | 1,000,000 | Photos, documents |
| 1 GB | 1 billion | Video hour (low quality) |
| 1 TB | 1 trillion | Small database |
| 1 PB | 1 quadrillion | Large scale storage |
| 1 Gbps → GB/s | 125 MB/s | Bits to bytes (/8) |
| 10 Gbps | 1.25 GB/s | Fast server NIC |
| 100 Gbps | 12.5 GB/s | Data center interconnect |
Latency Numbers:
| Operation | Latency | Notes |
|---|---|---|
| L1 cache reference | 0.5 ns | Fastest possible |
| L2 cache reference | 7 ns | On-CPU |
| Main memory reference | 100 ns | DRAM access |
| SSD random read | 150 μs | 150,000 ns |
| SSD sequential 1 MB | 1 ms | Fast storage |
| HDD seek | 10 ms | Mechanical |
| Same datacenter RTT | 0.5 ms | AZ to AZ |
| Cross-region RTT | 50-150 ms | Coast to coast |
| Intercontinental RTT | 100-300 ms | US to Europe/Asia |
Throughput Numbers:
| System | Throughput | Notes |
|---|---|---|
| Redis get/set | 100,000+ ops/sec | In-memory |
| PostgreSQL queries | 10,000-50,000 qps | Simple queries |
| PostgreSQL writes | 1,000-10,000 tps | With durability |
| Kafka throughput | 1M+ msgs/sec | Per partition |
| HTTP server (simple) | 10,000-50,000 RPS | Static/cached |
| HTTP server (complex) | 500-5,000 RPS | With business logic |
| Single thread CPU ops | 100M-1B ops/sec | Tight loops |
Notice how most numbers differ by powers of 10: 1ms vs 100ms vs 10s. 1KB vs 1MB vs 1GB. When estimating, round to the nearest power of 10. Being off by 2x doesn't matter; being off by 10x does.
When you need to estimate quickly—under time pressure in interviews or during incidents—use these shortcut techniques:
Technique 1: Powers of 2 for Storage
Memory and storage often use powers of 2. Memorize these:
2^10 = 1 KB (thousand)
2^20 = 1 MB (million)
2^30 = 1 GB (billion)
2^40 = 1 TB (trillion)
2^50 = 1 PB (quadrillion)
Technique 2: The 100K Seconds Trick
86,400 seconds per day ≈ 100,000 (10^5)
So for daily→per-second conversion:
123456789101112131415161718192021222324
# Quick estimation using the 100K trick def daily_to_rps(daily_count: int) -> float: """Convert daily count to approximate RPS using 100K trick""" return daily_count / 100_000 # Examplesprint("Daily to RPS conversions (quick method):")print(f" 1 billion/day → {daily_to_rps(1_000_000_000):,.0f} RPS")print(f" 100 million/day → {daily_to_rps(100_000_000):,.0f} RPS")print(f" 10 million/day → {daily_to_rps(10_000_000):,.0f} RPS")print(f" 1 million/day → {daily_to_rps(1_000_000):,.0f} RPS") # Verify accuracydef accurate_conversion(daily_count: int) -> float: return daily_count / 86_400 print("Accuracy check:")for daily in [1_000_000_000, 100_000_000, 10_000_000]: quick = daily_to_rps(daily) accurate = accurate_conversion(daily) error = abs(quick - accurate) / accurate * 100 print(f" {daily:,}/day: Quick={quick:,.0f}, Accurate={accurate:,.0f}, Error={error:.1f}%")Technique 3: The 2.5 Million Seconds/Month
30 days × 86,400 ≈ 2.5 million seconds per month
Technique 4: Bits/Bytes Quick Multiply
To convert Gbps to MB/s, divide by 8 and multiply by 1000:
Quick mental rule: Gbps → MB/s: multiply by 125
Technique 5: Order of Magnitude Validation
After any calculation, sanity check:
In interviews, use round numbers: 100M not 97.3M, 1 billion not 1.073B. Round to 1, 2, 5, or 10 × powers of 10. This makes mental math fast while maintaining accuracy within the order of magnitude that matters.
Even experienced engineers make these estimation errors. Knowing the pitfalls helps you avoid them:
Mistake 1: Forgetting the Bits/Bytes Conversion
Mistake 2: Using Average Instead of Peak
Mistake 3: Ignoring Replication and Overhead
Mistake 4: Assuming Linear Scaling
Mistake 5: Forgetting About Time (Retention)
Don't calculate exact numbers like 127,345.72 RPS. This implies false precision when your inputs (DAU, actions/user) are estimates. Say '~130K RPS' or 'roughly 100K-150K RPS.' Ranges communicate appropriate confidence levels.
Let's walk through a complete estimation for a Twitter-like social media platform to demonstrate how all the pieces fit together.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
"""Complete Back-of-Envelope Estimation: Twitter Clone=====================================================""" # ===================# 1. TRAFFIC ESTIMATION# =================== # User metricstotal_users = 500_000_000 # 500M registered usersdau = 200_000_000 # 200M DAU (40% engagement)mau = 350_000_000 # 350M MAUdau_mau_ratio = dau / mau # ~57% stickiness # User behaviortweets_per_user_day = 0.5 # Average (many read-only)feed_views_per_user = 10 # Feed refresheslikes_per_user = 20 # Likes givenprofile_views_per_user = 5 # Profile views # Calculate operations per daytweets_per_day = dau * tweets_per_user_day # 100M tweets/dayfeed_views_per_day = dau * feed_views_per_user # 2B feed views/daylikes_per_day = dau * likes_per_user # 4B likes/dayprofile_views_per_day = dau * profile_views_per_user # 1B profile views/day # API calls per operationtweets_per_tweet = 5 # Write + fan-out + notifytweets_per_feed_view = 25 # Multiple API callstweets_per_like = 3 # Update + notify + record # Total daily API callswrite_api_calls = tweets_per_day * tweets_per_tweetread_api_calls = ( feed_views_per_day * tweets_per_feed_view + profile_views_per_day * 15 + likes_per_day * tweets_per_like)total_api_calls = write_api_calls + read_api_calls # Convert to RPSaverage_rps = total_api_calls / 86_400peak_rps = average_rps * 3 print("=== TRAFFIC ESTIMATION ===")print(f"DAU: {dau/1e6:.0f}M")print(f"Daily API calls: {total_api_calls/1e12:.1f} trillion")print(f"Average RPS: {average_rps/1e6:.1f}M")print(f"Peak RPS: {peak_rps/1e6:.1f}M")print(f"Read:Write ratio: {read_api_calls/write_api_calls:.0f}:1") # ===================# 2. STORAGE ESTIMATION# =================== # Tweet storagetweet_size_bytes = 500 # Text + metadatatweets_yearly = tweets_per_day * 365tweet_storage_yearly = tweets_yearly * tweet_size_bytes # Media storage (30% of tweets have media)media_tweets_ratio = 0.30avg_media_size_mb = 3 # All resolutionsmedia_storage_yearly = tweets_yearly * media_tweets_ratio * avg_media_size_mb * 1e6 # User data (500M users × 2KB each)user_storage = total_users * 2000 # Engagement data (likes, retweets, follows)engagement_events_daily = likes_per_day + tweets_per_day * 2 # likes + RTsengagement_record_bytes = 32engagement_storage_yearly = engagement_events_daily * 365 * engagement_record_bytes # Total raw storagetotal_raw_storage = ( tweet_storage_yearly + media_storage_yearly + user_storage + engagement_storage_yearly) # With replication and overheadstorage_multiplier = 3 * 1.5 # 3x replication, 50% overheadtotal_production_storage = total_raw_storage * storage_multiplier print(f"=== STORAGE ESTIMATION ===")print(f"Tweets/year: {tweets_yearly/1e9:.0f}B")print(f"Tweet storage/year: {tweet_storage_yearly/1e15:.2f} PB")print(f"Media storage/year: {media_storage_yearly/1e15:.2f} PB")print(f"Total raw/year: {total_raw_storage/1e15:.2f} PB")print(f"Total production/year: {total_production_storage/1e15:.1f} PB") # ===================# 3. BANDWIDTH ESTIMATION# =================== # Egress (downloads)# Feed views dominate egressfeed_response_kb = 50 # JSON, no embedded mediamedia_views_per_day = feed_views_per_day * 5 # 5 media items per feed viewavg_media_view_kb = 200 # Lazy loaded, optimized egress_feed = feed_views_per_day * feed_response_kb * 1024egress_media = media_views_per_day * avg_media_view_kb * 1024total_daily_egress = egress_feed + egress_media # Convert to bandwidthegress_bps = (total_daily_egress * 8) / 86_400egress_gbps = egress_bps / 1e9peak_egress_gbps = egress_gbps * 3 # CDN impactcdn_hit_ratio = 0.90origin_egress_gbps = peak_egress_gbps * (1 - cdn_hit_ratio) print(f"=== BANDWIDTH ESTIMATION ===")print(f"Daily egress: {total_daily_egress/1e15:.2f} PB")print(f"Average egress: {egress_gbps/1000:.1f} Tbps")print(f"Peak egress: {peak_egress_gbps/1000:.1f} Tbps")print(f"Origin (10% cache miss): {origin_egress_gbps:.0f} Gbps") # ===================# 4. SERVER ESTIMATION# =================== # Application servers (handles API)rps_per_app_server = 2000 # Mixed read/writebase_app_servers = peak_rps / rps_per_app_server # Apply redundancy (3 AZs, survive 1)app_servers_with_az = base_app_servers * 1.5# Deployment overheadapp_servers_with_deploy = app_servers_with_az * 1.15# Spike headroomapp_servers_final = app_servers_with_deploy * 1.2 # Cache layer (Redis)hot_data_gb = 500 # Recently accessed tweets, trendingredis_instance_gb = 64redis_instances = (hot_data_gb * 3) / redis_instance_gb # 3x for replication # Database (distributed)# Assume DynamoDB/Cassandra style - estimate by write throughputwrite_rps = peak_rps * 0.01 # 1% writes at peakwrites_per_db_node = 10_000db_nodes = write_rps / writes_per_db_node * 3 # 3x replication print(f"=== SERVER ESTIMATION ===")print(f"App servers (base): {base_app_servers:,.0f}")print(f"App servers (production): {app_servers_final:,.0f}")print(f"Redis instances: {redis_instances:.0f}")print(f"Database nodes: {db_nodes:.0f}") # ===================# 5. SUMMARY# ===================print(f"{'='*50}")print("TWITTER CLONE ESTIMATION SUMMARY")print(f"{'='*50}")print(f"DAU: {dau/1e6:.0f} million")print(f"Peak RPS: {peak_rps/1e6:.1f} million")print(f"Annual storage: {total_production_storage/1e15:.1f} PB")print(f"Peak bandwidth: {peak_egress_gbps/1000:.1f} Tbps")print(f"Application servers: ~{round(app_servers_final, -2):,.0f}")print(f"Cache instances: ~{round(redis_instances, -1):.0f}")print(f"Database nodes: ~{round(db_nodes, -1):.0f}")Practice builds intuition. Work through these problems before checking the solutions.
Problem 1: URL Shortener
Given:
Calculate:
Problem 2: Video Streaming Service
Given:
Calculate:
Problem 3: Chat Application
Given:
Calculate:
Work through these problems on paper before looking at the solutions. The act of struggling with the estimation builds the intuition you need for interviews. Set a timer for 5 minutes per problem.
Solution 1: URL Shortener
12345678910111213141516171819202122232425262728293031323334353637
# URL Shortener Solution # Givenurl_creations_month = 500_000_000clicks_per_url = 50retention = "forever" # 5 years for calculation # Trafficwrites_per_second = url_creations_month / (30 * 86_400)reads_per_second = writes_per_second * clicks_per_url print("URL Shortener Traffic:")print(f" Write RPS: {writes_per_second:,.0f} (×3 peak = {writes_per_second*3:,.0f})")print(f" Read RPS: {reads_per_second:,.0f} (×3 peak = {reads_per_second*3:,.0f})")print(f" Read:Write ratio: {clicks_per_url}:1") # Storageurl_record_bytes = 200 # short_code + long_url + metadataurls_in_5_years = url_creations_month * 12 * 5storage_raw = urls_in_5_years * url_record_bytesstorage_production = storage_raw * 3 * 1.5 # replication + overhead print(f"URL Shortener Storage (5 years):")print(f" URLs created: {urls_in_5_years/1e9:.0f}B")print(f" Raw storage: {storage_raw/1e12:.1f} TB")print(f" Production storage: {storage_production/1e12:.1f} TB") # Bandwidth (reads return 302 redirect, minimal)redirect_response_bytes = 300daily_bandwidth = reads_per_second * 86400 * redirect_response_bytesbandwidth_mbps = (reads_per_second * 3 * redirect_response_bytes * 8) / 1e6 print(f"URL Shortener Bandwidth:")print(f" Daily transfer: {daily_bandwidth/1e9:.1f} GB")print(f" Peak bandwidth: {bandwidth_mbps:.0f} Mbps")Solution 2: Video Streaming Service
12345678910111213141516171819202122232425262728293031323334
# Video Streaming Solution # Givendau = 10_000_000hours_per_user = 2avg_bitrate_mbps = 5concurrent_ratio = 0.10 # Concurrent viewersconcurrent_viewers = dau * concurrent_ratiopeak_concurrent = concurrent_viewers * 1.5 # Peak is 1.5x average print("Video Streaming - Concurrent Viewers:")print(f" Average concurrent: {concurrent_viewers/1e6:.1f}M")print(f" Peak concurrent: {peak_concurrent/1e6:.1f}M") # Bandwidth at peakpeak_bandwidth_mbps = peak_concurrent * avg_bitrate_mbpspeak_bandwidth_tbps = peak_bandwidth_mbps / 1e6 print(f"Video Streaming - Bandwidth:")print(f" Peak bandwidth: {peak_bandwidth_tbps:.1f} Tbps") # Daily data transfertotal_viewing_hours = dau * hours_per_userdata_per_hour_gb = (avg_bitrate_mbps * 3600) / (8 * 1024) # Mbps to GBdaily_data_pb = (total_viewing_hours * data_per_hour_gb) / 1e6 print(f"Video Streaming - Daily Transfer:")print(f" Total viewing hours: {total_viewing_hours/1e6:.0f}M hours")print(f" Data per hour: {data_per_hour_gb:.1f} GB")print(f" Daily transfer: {daily_data_pb:.1f} PB")Solution 3: Chat Application
123456789101112131415161718192021222324252627282930313233343536373839
# Chat Application Solution # Givendau = 50_000_000messages_per_user = 100msg_size_bytes = 500retention_days = 30 # Messages per seconddaily_messages = dau * messages_per_usermessages_per_second = daily_messages / 86_400peak_mps = messages_per_second * 3 print("Chat Application - Message Rate:")print(f" Daily messages: {daily_messages/1e9:.0f}B")print(f" Average MPS: {messages_per_second/1e3:.0f}K")print(f" Peak MPS: {peak_mps/1e3:.0f}K") # Storage (30-day rolling)messages_retained = daily_messages * retention_daysraw_storage = messages_retained * msg_size_bytesproduction_storage = raw_storage * 3 * 1.5 print(f"Chat Application - Storage:")print(f" Messages retained: {messages_retained/1e9:.0f}B")print(f" Raw storage: {raw_storage/1e12:.1f} TB")print(f" Production storage: {production_storage/1e12:.1f} TB") # WebSocket connections# Assume 60% DAU online at peak, each with 1 connectionconcurrent_connections = dau * 0.60# Distribute across servers (each handles ~50K connections)ws_servers = concurrent_connections / 50_000 print(f"Chat Application - Connections:")print(f" Peak concurrent connections: {concurrent_connections/1e6:.0f}M")print(f" WebSocket servers needed: {ws_servers:.0f}")Print this mental checklist for quick reference before interviews:
Step 1: Clarify Requirements (1-2 min)
Step 2: Key Assumptions (1 min)
Step 3: Traffic Estimation (2-3 min)
Step 4: Storage Estimation (2-3 min)
Step 5: Bandwidth (1-2 min)
Step 6: Server Count (2-3 min)
Step 7: Sanity Check (30 sec)
| Remember | Value | Usage |
|---|---|---|
| Seconds/day | ~100,000 | Easy division |
| Seconds/month | ~2.5M | Monthly to RPS |
| Peak multiplier | 3x | Default assumption |
| Storage overhead | 3-5x | Replication + indexes |
| CDN hit ratio | 90-95% | Reduces origin load |
| AZ redundancy | 1.5x | Survive 1 AZ failure |
| vCPU benchmark | 1-5K RPS | Simple API servers |
The goal of back-of-envelope estimation isn't precision—it's demonstrating you can reason quantitatively about systems. Interviewers are evaluating your thought process and awareness of scale, not your arithmetic. Stay calm, state assumptions clearly, and show your work.
Congratulations! You've completed the comprehensive guide to back-of-envelope estimation. Let's consolidate what you've learned:
The Estimation Mindset:
Order of magnitude matters, not precision — 100K vs 1M is significant; 100K vs 130K is not
State assumptions explicitly — Makes your reasoning transparent and adjustable
Always apply safety factors — Peak traffic, redundancy, and operational headroom
Sanity check against reality — Compare to known systems; if Twitter needs 1000 servers, your 100M-user system shouldn't need 10,000
Practice makes intuitive — After estimating 50 systems, you'll have instant intuition for scale
You now possess the quantitative skills that separate junior engineers from senior ones. These estimation abilities apply to every system design interview and every capacity planning conversation in your career. Next, you'll learn how to take these estimated requirements and synthesize them into high-level system designs.