Module 2: Napkin Estimation (Back-of-the-Envelope)
2. The tools: powers of 10, seconds per day, and units
Description
Before computing Enlace's four numbers you need a mental toolkit that makes napkin arithmetic fast and error-proof. It's not hard math —it's grade-school arithmetic— but it has three traps that sink a lot of people: getting lost counting zeros, messing up time conversions (how many seconds does a day, a month, a year have?), and confusing data units (is a gigabyte a billion bytes or a billion forty-eight million?). This lesson gives you the three pieces: powers of 10 to count zeros without getting dizzy, the handful of time constants worth memorizing, and the data units (KB, MB, GB, TB) with their base-1000-vs-1024 trap.
The lesson's promise is concrete: by the end you'll be able to multiply and divide enormous numbers in your head, no calculator, by counting zeros; you'll know by heart that a month is ~2.6 million seconds and a day ~86,400; and you'll be able to go from "6 billion 1 KB records" to "6 TB" without hesitating. They're the multiplication tables of estimation: boring to learn, indispensable for everything else.
Connection to the module: this is the tool-lesson. It doesn't estimate any Enlace number yet; it sharpens the instruments that lessons 3 to 6 will use without re-explaining them. When in lesson 3 we write "100M / 2.6M s ≈ 40/s" and don't stop to justify where the 2.6 million seconds come from, it's because you nailed it down here. Think of it as the moment of organizing the toolbox before starting the job.
The carpenter's toolbox
A carpenter doesn't calculate from scratch how long a foot is or how many centimeters an inch has every time they cut a board: they have those conversions memorized and their tape measure at hand, and that's why they cut fast and without errors. Their speed doesn't come from thinking more, but from not having to think about the basic conversions: they have them automated and spend their attention on the design of the furniture, not on the arithmetic.
Systems estimation is the same. The interesting calculations —does it fit in a server?, do I need a cache?— deserve all your attention. The mechanical conversions —seconds in a month, bytes in a gigabyte— shouldn't cost you a single neuron: they should come out on their own. That's why this lesson is an exercise in deliberate memorization of a small handful of constants and a trick (counting zeros) that turns the multiplication of giant numbers into a sum of small digits. You invest twenty minutes to nail down the kit and you recover it every time you estimate for the rest of your career.
And like the carpenter with their tape measure, not everything has to be memorized: some things are calculated on the spot, but fast, because you master the tool. The goal isn't to know a hundred numbers, but to have five memorized and be able to derive the rest in seconds.
Tool 1: powers of 10 (counting zeros instead of multiplying)
A power of 10 is a 1 followed by zeros: 10³ is 1 followed by 3 zeros = 1,000; 10⁶ is 1 followed by 6 zeros = 1,000,000. The exponent is the number of zeros. Writing a number as a power of 10 (or as a digit times a power of 10, like 4 × 10³) is called scientific notation, and it's how people who estimate think about large numbers, because it turns heavy arithmetic into exponent arithmetic.
A note for the module's Python snippets: in code, scientific notation is written with e. 1e8 is 10⁸ (100 million), 2.6e6 is 2.6 × 10⁶, 5e2 is 500. The e reads "times ten to the". It's the same napkin notation, typeable: when you see writes = 1e8 in a snippet, read it as "a hundred million" and not as a weird number. Python understands it out of the box and prints it back when the numbers grow.
The golden rule, the one that makes the whole module magic:
Multiplying powers of 10 = adding exponents. Dividing = subtracting exponents.
10⁸ × 10³ = 10¹¹ (you add: 8 + 3 = 11). 10⁸ ÷ 10⁶ = 10² (you subtract: 8 − 6 = 2). You don't multiply or divide anything: you count zeros. And since we saw in lesson 1 that the only thing that matters is the order of magnitude, this trick isn't a dirty shortcut: it's exactly the precision you need.
This is the table worth having in your head. Watch the Spanish-name column, which hides a famous trap:
| Power | Number | Name (Spanish) | Name (English) | Data prefix |
|---|---|---|---|---|
| 10³ | 1,000 | mil | thousand | K (kilo) |
| 10⁶ | 1,000,000 | un millón | million | M (mega) |
| 10⁹ | 1,000,000,000 | mil millones | billion | G (giga) |
| 10¹² | 1,000,000,000,000 | un billón | trillion | T (tera) |
| 10¹⁵ | 1,000,000,000,000,000 | mil billones | quadrillion | P (peta) |
The "billion" trap. In Spanish, a billón is 10¹² (a million millions). In English, billion is 10⁹ (a thousand millions). They aren't the same, and confusing them is an error of a thousand times. Since code and many technical sources are in English, a bilingual engineer has to have this crystal clear: when in English you read "3 billion records", in Spanish that's 3 thousand million records (3 × 10⁹), not 3 billones. Enlace's 6 billion records are 6 billion in English and 6 mil millones in Spanish. And the 3.5 × 10¹² possible base62 codes really are 3.5 billones in Spanish (and 3.5 trillion in English). When in doubt, go back to the power of 10: it's the only notation that doesn't lie in any language.
Worked example: the read QPS by counting zeros
You already computed in lesson 1 that Enlace does ~40 writes/s and ~4,000 reads/s. Let's redo it without dividing long numbers, only with exponents, so you see the tool in action.
It's 100 million writes a month. 100 million is 10⁸. A month is ~2.6 million seconds, which is on the order of 10⁶ (with a 2.6 factor in front). Then:
qps_write ≈ 10⁸ / (2.6 × 10⁶) = (1 / 2.6) × 10⁸⁻⁶ = 0.38 × 10² = 38 ≈ 40/s
You counted zeros: 8 − 6 = 2, so the result is on the order of 10² = 100, and the factor 1/2.6 ≈ 0.38 brings it down to ~40. And the read, ×100 = ×10²:
qps_read ≈ 40 × 10² = 4,000/s
Let's verify it in Python to confirm that counting zeros gives the same as the raw division:
# Counting zeros (scientific notation) vs raw division: same result.
writes = 1e8 # 10^8 (100 million)
sec_month = 2.592e6 # ~2.6 x 10^6
qps_write = writes / sec_month
qps_read = qps_write * 1e2 # x100
print(f"qps_write = {qps_write:.1f}/s (order 10^{len(str(int(qps_write)))-1})")
print(f"qps_read = {qps_read:.0f}/s")
What to expect. The output:
qps_write = 38.6/s (order 10^1)
qps_read = 4000/s
38.6/s, order 10¹ (tens), which you round to ~40; and 4,000/s, order 10³ (thousands). The same numbers as lesson 1, but obtained by counting zeros instead of operating on digits. That's the tool: for order of magnitude, the subtraction of exponents gives you the correct mark and the front factor fine-tunes it. With practice you do it in your head in two seconds.
Working with the mantissa: when the number isn't a bare 1
Almost no real number is a 1 followed by zeros. 100 million is (10⁸), but "2.6 million seconds" is 2.6 × 10⁶, and that 2.6 in front has a name: the mantissa (or coefficient). Scientific notation separates each number into two parts: a mantissa between 1 and 10, and a power of 10. 2,592,000 is written 2.6 × 10⁶; 4,000 is 4 × 10³; 86,400 is 8.64 × 10⁴.
The arithmetic is done in two independent lanes that don't cross: the mantissas are multiplied or divided by each other like small numbers, and the exponents are added or subtracted. Example with the write QPS calculation:
10⁸ / (2.6 × 10⁶)
= (1 / 2.6) × 10⁽⁸⁻⁶⁾ ← mantissas in one lane, exponents in the other
= 0.38 × 10²
= 38
The exponent lane (8 − 6 = 2) gives you the mark: we're in the tens-hundreds. The mantissa lane (1 / 2.6 ≈ 0.38) fine-tunes within the mark. Divide and conquer: you never operate 100000000 / 2592000 in your head; you operate 1/2.6 (easy, ~0.4) and 10⁸/10⁶ (trivial, 10²) separately, and you join them at the end.
A hygiene detail: the mantissa should stay between 1 and 10. If you get 0.38 × 10², move it to 3.8 × 10¹ (you shift the point one place to the right and lower the exponent by one). 38 = 3.8 × 10¹, order 10¹, tens. This "normalizing" keeps you from getting the mark wrong at the end. With two or three calculations it comes out on its own.
The order-of-magnitude line
It helps to have a mental line where each mark is a power of 10, and to know which mark each Enlace number falls on. That way, when you compute something, the first thing you check is "which mark did it land on?", and that already tells you almost everything:
10⁰ 10¹ 10² 10³ 10⁴ 10⁵ 10⁶ 10⁷ 10⁸ 10⁹ 10¹²
1 10 100 1k 10k 100k 1M 10M 100M 1G 1T
│ │ │ │ │ │ │ │ │ │ │
QPS write ●40 (tens/s)
QPS read ●4000 (thousands/s)
URLs/month ●100M (10⁸/month)
Records 5y ●6G (6×10⁹)
Storage ●6T (6×10¹² B)
Notice how the horizontal distance is the factor between two numbers: the read QPS (10³) is three marks to the right of the write one (10⁰-10¹), which visualizes the "100 times more" at a glance. And the storage (10¹²) is far to the right of everything else, which warns you at once that "total bytes" are on a completely different scale from "requests per second" —an obvious thing said this way, but easy to confuse when the numbers are loose on a sheet—. Training your eye to place each result on this line is the best defense against the mark error we talked about in lesson 1.
Tool 2: the time constants
The conversion you'll do most in all of estimation is "per unit of time" ↔ "per second", because prompts come in "per month" or "per day" and QPS is asked "per second". You need to have these three memorized, and to know how to derive the rest:
| Period | Seconds | Rounded | In scientific notation |
|---|---|---|---|
| 1 day | 86,400 | ~86,400 (or ~10⁵) | 8.64 × 10⁴ |
| 1 month (30 days) | 2,592,000 | ~2.6 million | 2.6 × 10⁶ |
| 1 year (365 days) | 31,536,000 | ~31.5 million | 3.15 × 10⁷ |
Of these three, the queen is seconds per day = 86,400. It comes from 24 × 3,600 (24 hours × 3,600 seconds per hour), and it appears in almost every calculation. Memorize it as an exact number: 86,400. The other two derive from it (× 30 for the month, × 365 for the year), but it's good to have them at hand too.
A couple of clarifications about the month and the year. We use 30 days per month —not 30.44, the real average— because we seek a round number and the difference (1.5%) disappears in the final rounding. It doesn't matter that February has 28 and July 31: for napkin math, a month is 30 days, period. And we use 365 days per year, ignoring leap years (0.07% more), for the same reason. The discipline is always the same: choose the round number that lets you count zeros, and don't apologize for the decimal you drop, because it's smaller than the uncertainty of your input assumptions. A "30-day" month isn't an error; it's a deliberate choice that buys speed in exchange for a precision you didn't have anyway.
The 10⁵ seconds-per-day shortcut. Many people round 86,400 to 10⁵ = 100,000 to count zeros more easily. It's convenient, but careful: 100,000 is 15.7% more than 86,400, so using 10⁵ overestimates the time and therefore underestimates the QPS by that 15.7%. For an "order of magnitude" answer it doesn't matter (you're still on the same mark); but if you want the number a bit finer, stick with 86,400. The practical rule: use 10⁵ for fast mental calculation and 86,400 when you write the calculation "cleanly". The module uses 86,400.
The "π × 10⁷ seconds per year" trick. A year has 31,536,000 seconds ≈ 3.15 × 10⁷. It happens that π ≈ 3.14159, so a year ≈ π × 10⁷ seconds. It's one of those coincidences that veteran estimators use to remember the number: "the seconds in a year are pi times ten to the seven". You don't need it for Enlace (we work per month), but you'll see it cited and now you know where it comes from.
# The time constants, derived from the queen (86,400).
sec_day = 24 * 3600
sec_month = 30 * sec_day
sec_year = 365 * sec_day
print(f"seconds/day = {sec_day:,}")
print(f"seconds/month = {sec_month:,}")
print(f"seconds/year = {sec_year:,} (~pi x 10^7 = {3.14159*1e7:,.0f})")
What to expect.
seconds/day = 86,400
seconds/month = 2,592,000
seconds/year = 31,536,000 (~pi x 10^7 = 31,415,900)
Notice how close π × 10⁷ (31,415,900) is to the real value (31,536,000): a 0.4% difference. For napkin math, identical.
Tool 3: the data units (and the base-1000-vs-1024 trap)
Data sizes are measured in bytes, and since bytes are many, they're grouped with prefixes: KB, MB, GB, TB. Here there's a historical trap that confuses everyone, so it's worth resolving once and for all.
There are two conventions for what those prefixes mean:
- Base 10 (decimal, SI): KB = 10³ = 1,000 bytes; MB = 10⁶; GB = 10⁹; TB = 10¹². It's the one disk manufacturers use and the one that aligns with the powers of 10 you already master.
- Base 2 (binary): 1,024 instead of 1,000, because computers count in powers of 2 and 2¹⁰ = 1,024 is the power of 2 closest to a thousand. To avoid the ambiguity, dedicated names were invented: KiB (kibibyte) = 2¹⁰ = 1,024; MiB = 2²⁰; GiB = 2³⁰; TiB = 2⁴⁰. It's the one operating systems usually report.
The difference grows with each step:
| Prefix | Base 10 (SI) | Base 2 (IEC) | Difference |
|---|---|---|---|
| K | 10³ = 1,000 | 2¹⁰ = 1,024 | +2.4% |
| M | 10⁶ = 1,000,000 | 2²⁰ = 1,048,576 | +4.9% |
| G | 10⁹ = 1,000,000,000 | 2³⁰ = 1,073,741,824 | +7.4% |
| T | 10¹² = 1,000,000,000,000 | 2⁴⁰ = 1,099,511,627,776 | +10.0% |
This table we compute, we don't quote:
# How much base 10 and base 2 diverge at each step.
for name, e in [("K", 1), ("M", 2), ("G", 3), ("T", 4)]:
base10 = 10 ** (3 * e)
base2 = 2 ** (10 * e)
diff = 100 * (base2 / base10 - 1)
print(f"{name}: base10 = {base10:>16,} base2 = {base2:>19,} diff = +{diff:.1f}%")
What to expect.
K: base10 = 1,000 base2 = 1,024 diff = +2.4%
M: base10 = 1,000,000 base2 = 1,048,576 diff = +4.9%
G: base10 = 1,000,000,000 base2 = 1,073,741,824 diff = +7.4%
T: base10 = 1,000,000,000,000 base2 = 1,099,511,627,776 diff = +10.0%
Where did the 1,024 come from? The story fits in a paragraph and helps remember which is which. Computers address memory in powers of 2, and 2¹⁰ = 1,024 turned out to be astonishingly close to a thousand (within 2.4%), so in the early days of computing people started calling those 1,024 bytes "kilo" for convenience, even though "kilo" in the rest of the world (kilometers, kilograms) always meant exactly 1,000. From there the ambiguity was born: a "kilobyte" could be 1,000 or 1,024 depending on who was speaking. In 1998 the IEC settled the matter by inventing explicit binary prefixes —kibi, mebi, gibi, tebi (KiB, MiB, GiB, TiB)— for the 1,024, leaving kilo/mega/giga/tera for the clean 1,000. Adoption was half-hearted: disk manufacturers use base 10 (which is why a "1 TB" disk is 10¹² bytes), while many operating systems still report in base 2 but label it "GB" instead of "GiB". That's why your "1 TB" disk shows up as "931 GB" in the file explorer: it's the same 10¹² bytes, but the system divides them by 2³⁰ and keeps writing "GB". You didn't lose space; they counted it in another base.
Which do I use to estimate? Base 10, always. For napkin math use base 10 (1 KB = 1,000 bytes, 1 TB = 10¹² bytes) for two reasons: first, it fits with the powers of 10 you already count by heart, so it doesn't break the flow; second, the maximum difference (10% at TB) is smaller than the uncertainty of your assumptions. If you're not sure whether the record weighs 1 KB or 1.2 KB, arguing whether a TB is 10¹² or 2⁴⁰ bytes is sharpening the handle while the axe is crooked. Use base 10, round, and move on. Save the binary units (KiB, GiB) for when you measure a real system and the operating system reports them to you that way.
That's why, when in lesson 4 we say that 6 billion 1 KB records are "6 TB", we'll be using base 10: 6 × 10⁹ × 10³ = 6 × 10¹² bytes = 6 TB. In base 2 it would be ~5.6 TiB —the same size for any design decision—.
The conversion table you'll use most
To avoid deriving them each time, these are the conversions that appear over and over when estimating. All in base 10:
| From | To | Multiply by | Example in Enlace |
|---|---|---|---|
| per month | per second | ÷ 2.6 × 10⁶ | 100M/month → ~40/s |
| per day | per second | ÷ 86,400 | 345.6M reads/day → 4,000/s |
| bytes | KB | ÷ 10³ | 500 B → 0.5 KB |
| bytes | MB | ÷ 10⁶ | 2 × 10⁶ B/s → 2 MB/s |
| bytes | GB | ÷ 10⁹ | 3.3 × 10⁸ B → 0.33 GB |
| bytes | TB | ÷ 10¹² | 6 × 10¹² B → 6 TB |
| QPS × payload | bytes/s | multiply | 4,000/s × 500 B → 2 MB/s |
None is hard; the value of having them together is that you see the pattern at a glance: everything is multiplying or dividing by a power of 10, that is, shifting the decimal point. Estimation has no single operation more complicated than that.
The minimal kit: what's worth memorizing
Of everything above, this is what's worth having by heart (the rest is derived):
TIME
1 day = 86,400 s (24 × 3,600) ~10⁵
1 month = 2.6 × 10⁶ s (× 30)
1 year = 3.15 × 10⁷ s (× 365) ~π × 10⁷
POWERS OF 10
thousand = 10³ (K) · million = 10⁶ (M) · billion = 10⁹ (G) · trillion = 10¹² (T)
multiply = add exponents · divide = subtract exponents
DATA (base 10 for estimating)
1 KB = 10³ B · 1 MB = 10⁶ B · 1 GB = 10⁹ B · 1 TB = 10¹² B
(base 2: KiB/MiB/GiB/TiB = 1024^n; +2.4% to +10%, ignorable in napkin math)
Eight lines. With that in place, Enlace's four estimates become a matter of minutes. Everything else in this module is applying this kit to an anchor number and rounding the result.
And for reference, here are Enlace's own anchor numbers translated to scientific notation, which is how it's best to have them in your head when estimating:
100 million URLs/month → 10⁸ / month
read:write ratio → × 10² (100:1)
retention → 5 years → 60 months ≈ 6 × 10¹ months
average long URL → 500 B = 5 × 10² B
complete record → ~1 KB = 10³ B
7-char base62 code → 62⁷ ≈ 3.5 × 10¹² combinations
With the inputs in powers of 10, each calculation in the module is an addition or subtraction of exponents with a mantissa adjustment. For example, "records in 5 years" is 10⁸/month × 6 × 10¹ months = 6 × 10⁹, and you already have the 6 billion without having multiplied anything long.
Worked example: the three tools together in one calculation
Let's close with a calculation that uses all three tools at once, so you see how they combine. The question: if Enlace receives 4,000 reads per second and each response returns the long URL (~500 bytes), how many gigabytes leave the server in a whole day? It's a preview of bandwidth (lesson 5), solved only with this lesson's kit.
Step by step, each tool does its part:
- Bytes per second (powers of 10, mantissas):
4,000/s × 500 B = (4 × 10³) × (5 × 10²) = 20 × 10⁵ = 2 × 10⁶ B/s. Mantissas 4 × 5 = 20, exponents 3 + 2 = 5, I normalize: 2 × 10⁶. - Per day (time constant): I multiply by the seconds of a day,
× 8.64 × 10⁴:2 × 10⁶ × 8.64 × 10⁴ = 17.3 × 10¹⁰ = 1.73 × 10¹¹ B/day. - To gigabytes (units, base 10): I divide by 10⁹:
1.73 × 10¹¹ / 10⁹ = 1.73 × 10² = 173 GB/day.
Let's verify it:
qps_read = 4000
payload_bytes = 500
bytes_per_sec = qps_read * payload_bytes
bytes_per_day = bytes_per_sec * 86_400
gb_per_day = bytes_per_day / 1e9
print(f"bytes/s = {bytes_per_sec:,} B/s = {bytes_per_sec/1e6:.0f} MB/s")
print(f"bytes/day = {bytes_per_day:,} B")
print(f"GB/day = {gb_per_day:.0f} GB/day")
What to expect.
bytes/s = 2,000,000 B/s = 2 MB/s
bytes/day = 172,800,000,000 B
GB/day = 173 GB/day
~173 GB a day of output, or ~2 MB/s sustained. Three tools, one calculation: powers of 10 for the QPS × payload product, a time constant to get to "per day", and a unit to report it in readable GB. This is literally the work of lessons 3 to 6, and you already did it. Everything that follows is more of the same, applied carefully to each of the four numbers.
Common mistakes
Confusing the Spanish "billón" with the English "billion" (translation error). What happens: someone reads "6 billion records" in an English source and translates it as "6 billones de registros", inflating the number by a thousand (6 × 10¹² instead of 6 × 10⁹). Why it happens: the languages use the same word for different numbers, and code and technical sources come in English. How to detect it: if your estimated Enlace storage comes out to "6,000 TB" instead of "6 TB", you probably mistranslated a "billion". How to fix it: never reason in words when there's ambiguity; reason in powers of 10. Billion = 10⁹ = mil millones (Spanish); billón (Spanish) = 10¹² = trillion (English). The power of 10 is language-neutral and doesn't lie.
Rounding the day's seconds to 10⁵ and forgetting it underestimates the QPS (a mis-measured shortcut). What happens: the person uses 100,000 seconds per day to go fast and reports a QPS that's ~15% lower than the real one, without knowing it. Why it happens: 10⁵ is convenient for counting zeros and the difference is subtle. How to detect it: if your QPS seems low and you used 10⁵ seconds/day, there's the bias. How to fix it: remember the direction of the error —using 100,000 instead of 86,400 enlarges the denominator, so it shrinks the QPS by 15.7%—. For order of magnitude it doesn't matter; if you want the fine number, use 86,400. What matters is knowing which way the shortcut lies.
Mixing base 10 and base 2 in the same calculation (inconsistency). What happens: someone computes the number of records with 1,000 (base 10) but converts to TB by dividing by 1,099,511,627,776 (base 2), mixing conventions and producing a number that's neither one thing nor the other. Why it happens: you drag different habits without noticing. How to detect it: if your calculation has a 1,024 in one step and a 1,000 in another for no reason, you're mixing. How to fix it: choose one base for the whole estimate —base 10 for napkin math— and be consistent. Consistency matters more than which you choose: the error of mixing is worse than the error of using the "less correct" one.
Exercises
Exercise 1 — Count zeros. Without a calculator, solve these three using only addition and subtraction of exponents, and give the result in scientific notation and as a rounded number: (a) 10⁸ × 10³; (b) (6 × 10⁹) × (10³); (c) (3.5 × 10¹²) / (6 × 10⁹).
See solution
- (a)
10⁸ × 10³ = 10⁸⁺³ = 10¹¹= a hundred billion (1 × 10¹¹). - (b)
6 × 10⁹ × 10³ = 6 × 10⁹⁺³ = 6 × 10¹²= 6 trillion... bytes, that is, 6 TB. (This is exactly Enlace's storage: 6 billion records × 1 KB.) - (c)
(3.5 × 10¹²) / (6 × 10⁹) = (3.5 / 6) × 10¹²⁻⁹ = 0.58 × 10³ ≈ 580. (This is the base62 code space —3.5 trillion— divided by Enlace's records —6 billion—: there are ~580 possible codes per record we'll ever have. Space to spare; module 3 develops it.)
In all three cases you didn't multiply or divide long numbers: you added or subtracted exponents and adjusted the front factor. That's all the arithmetic the module needs.
Exercise 2 — Convert time. A service receives 500 million events per day. (a) How many events per second, on average? (b) Express it rounded to one significant figure. (c) If the peak is 3 times the average, what's the approximate peak QPS?
See solution
- (a) 500 million = 5 × 10⁸. A day = 86,400 s ≈ 8.64 × 10⁴.
5 × 10⁸ / (8.64 × 10⁴) = (5 / 8.64) × 10⁴ ≈ 0.58 × 10⁴ ≈ 5,800/s. - (b) Rounded: ~6,000 events/s (or "on the order of thousands per second").
- (c) Peak = 3 × ~6,000 ≈ ~18,000/s, or "on the order of tens of thousands per second".
Check with the 10⁵ shortcut: 5 × 10⁸ / 10⁵ = 5 × 10³ = 5,000/s, a bit lower (~14% less) than the real 5,800, exactly as the bias of using 10⁵ instead of 86,400 predicts. Both round to "thousands per second", so for order of magnitude they give the same.
Exercise 3 — Units without traps. A system stores 2 billion photos, each 400 KB on average. (a) How much storage in total, in base 10? (b) Give the result in the most readable unit (not bytes). (c) Would your design decision change if you calculated it in base 2 (TiB)?
See solution
- (a) 2 billion = 2 × 10⁹ photos. 400 KB = 4 × 10⁵ bytes. Total =
2 × 10⁹ × 4 × 10⁵ = 8 × 10¹⁴ bytes. - (b) 8 × 10¹⁴ bytes = 8 × 10¹⁴ / 10¹² TB = 800 TB (almost a petabyte). An enormous number compared to Enlace's 6 TB: storing photos weighs much more than storing URLs, and that completely changes the design (here distributed storage does matter).
- (c) No. In base 2, 8 × 10¹⁴ bytes ≈ 727 TiB instead of 800 TB —9% less—. The design decision ("this doesn't fit in one server, I need distributed storage") is identical with 727 or with 800. It confirms the rule: the base doesn't change the mark, so for napkin math use base 10 and move on.
Summary and next step
In this lesson you assembled the estimation toolbox. You learned to think of large numbers as powers of 10 and to operate by counting zeros (multiply = add exponents, divide = subtract), which turns the arithmetic of giant numbers into arithmetic of small digits. You set the key time constants —day = 86,400 s, month ≈ 2.6 × 10⁶ s, year ≈ 3.15 × 10⁷ s (≈ π × 10⁷)— and saw the 10⁵ seconds/day shortcut with its 15.7% bias. And you resolved the units trap: base 10 (1 TB = 10¹² B) for estimating, base 2 (1 TiB = 2⁴⁰ B) for measuring real systems, with a difference (2.4% to 10%) that for napkin math is ignored. You closed with the minimal eight-line kit worth memorizing. And you found the language trap: English billion = 10⁹ = mil millones; Spanish billón = 10¹².
Before moving on you should be able to: multiply and divide powers of 10 in your head; say without thinking how many seconds a day, a month, and a year have; convert "N records of M bytes" to KB/MB/GB/TB in base 10; and explain why 3 billion in English isn't 3 billones in Spanish.
With the kit assembled, Enlace's four estimates are now almost mechanical. Lesson 3 attacks the first number and the most-used of all: the QPS. You'll convert "100M URLs a month" into writes per second, apply the 100:1 ratio for the reads, and —this is new— distinguish average traffic from peak, because a system is sized for the worst moment, not the middle ground.
Resources
- The System Design Primer, "Powers of two table" and "Latency numbers every programmer should know" sections — github.com/donnemartin/system-design-primer#appendix. It has the powers-of-2 table and the time conversions exactly as we use them here. Free, in English.
- IEC 80000-13, binary prefixes (kibi, mebi, gibi) — accessible summary at Wikipedia: Binary prefix. The reference for why KiB/MiB/GiB exist and how they differ from KB/MB/GB. Useful for understanding why your "1 TB" disk shows 931 GiB in the operating system.
- Martin Kleppmann, Designing Data-Intensive Applications, Chapter 1, "Describing Load" section — dataintensive.net. Formalizes how to describe a system's load with parameters (like the read/write ratio) before sizing it. The conceptual basis of this lesson's conversions.