ЁЯПл The SchoolтА║ЁЯУР System DesignтА║ЁЯУЛ рдзрдбрд╛ 01 тАФ рдЧрд░рдЬрд╛ рдЖрдгрд┐ рдорд░реНрдпрд╛рджрд╛: рдирд┐рдпреЛрдЬрди рдХрд╛рд░реНрдпрд╛рд▓рдп рдХрд╛рдврдгреНрдпрд╛рдЖрдзреА рд╡рд┐рдЪрд╛рд░рддреЗ
ЁЯЦ╝я╕П See the drawing + lab ЁЯПа Course home ЁЯМ┐ Branch on GitHub тЬПя╕П View source
ЁЯЦ╝я╕П рдЖрдХреГрддреА рдЖрдгрд┐ labThe drawing + lab рдкреВрд░реНрдг рдкрд╛рдирд╛рд╡рд░ рдЙрдШрдбрд╛ тЖЧOpen full page тЖЧ

ЁЯУЛ рдзрдбрд╛ 01 тАФ рдЧрд░рдЬрд╛ рдЖрдгрд┐ рдорд░реНрдпрд╛рджрд╛: рдирд┐рдпреЛрдЬрди рдХрд╛рд░реНрдпрд╛рд▓рдп рдХрд╛рдврдгреНрдпрд╛рдЖрдзреА рд╡рд┐рдЪрд╛рд░рддреЗ

ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 18 рдкреИрдХреА рдзрдбрд╛ 01 ┬╖ рдкреБрдвреЗ: lesson-02-capacity


ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ

рд╣рд╛ рд╕рдВрдкреВрд░реНрдг рдХреЛрд░реНрд╕ рдЬреНрдпрд╛ рдПрдХрд╛ рд╕рд╡рдпреАрд╡рд░ рдЙрднрд╛ рдЖрд╣реЗ рддреА: рдПрдХрд╣реА box рдХрд╛рдврдгреНрдпрд╛рдЖрдзреА, system рдиреЗ рдХрд╛рдп рдХрд░рд╛рдпрдЪреЗ, рдХрд┐рддреА рдЪрд╛рдВрдЧрд▓реЗ, рдЖрдгрд┐ рдХреЛрдгрддреНрдпрд╛ рдорд░реНрдпрд╛рджреЗрдд тАФ рд╣реЗ рд▓рд┐рд╣реВрди рдареЗрд╡рд╛. рдХрд╛рдо рдПрдХрд╛ рдУрд│реАрдЪреЗ рдЖрд╣реЗ тАФ "5 million рдкрд╛рд▓рдХрд╛рдВрд╕рд╛рдареА рд╕реВрдЪрдирд╛ рдлрд▓рдХ app рдмрдирд╡рд╛" тАФ рдЖрдгрд┐ рдпрд╛ рдзрдбреНрдпрд╛рдд рддреЗ рдЪрд╛рд░ рднрд╛рдЧрд╛рдВрдЪрд╛ рдПрдХ рдХрд╛рдЧрдж рдмрдирддреЗ: functional рдЧрд░рдЬрд╛, рдЖрдХрдбреНрдпрд╛рдВрд╕рд╣ non-functional рдЧрд░рдЬрд╛, рдорд░реНрдпрд╛рджрд╛ (constraints) рдЖрдгрд┐ рдХрдХреНрд╖реЗрдмрд╛рд╣реЗрд░ (out of scope), рд╕реЛрдмрдд рдХрд╛рдо рджреЗрдгрд╛рд▒реНрдпрд╛ рд╡реНрдпрдХреНрддреАрд▓рд╛ рд╡рд┐рдЪрд╛рд░рд╛рдпрдЪреЗ рдкреНрд░рд╢реНрди. рд╕рдВрдкреВрд░реНрдг рдХреЛрд░реНрд╕рднрд░ рддреБрдореНрд╣реА рд╡рд╛рдкрд░рд╛рд▓ рдЕрд╢рд╛ рдЦрд▒реНрдпрд╛ files:

ЁЯОТ рд╕реБрд░реВ рдХрд░рдгреНрдпрд╛рдЖрдзреА: рддреБрдореНрд╣рд╛рд▓рд╛ рдлрдХреНрдд Python 3 рд▓рд╛рдЧреЗрд▓, рдмрд╛рдХреА рдХрд╛рд╣реА рдирд╛рд╣реА тАФ cloud account рдирд╛рд╣реА, pip install рдирд╛рд╣реА. рдпрд╛ files рдордзреНрдпреЗ рдЧреЛрд▓ рдЙрджрд╛рд╣рд░рдгрд╛рдЪреНрдпрд╛ рдЖрдХрдбреНрдпрд╛рдВрд╕рд╣ рд╢рд┐рдХрд╡рдгреНрдпрд╛рд╕рд╛рдареАрдЪреЗ models рдЖрд╣реЗрдд (рдкреНрд░рддреНрдпреЗрдХ server рд▓рд╛ рд╕реЗрдХрдВрджрд╛рд▓рд╛ 500 requests, рдкреНрд░рддреНрдпреЗрдХ рд╕реВрдЪрдиреЗрд▓рд╛ 2 KB, 3├Ч рдЪрд╛ peak). рдЕрдВрдХрд╛рдВрдкреЗрдХреНрд╖рд╛ рдкрджреНрдзрдд рдЬрд╛рд╕реНрдд рдорд╣рддреНрддреНрд╡рд╛рдЪреА рдЖрд╣реЗ. on a real account рдЕрд╢реА рдЦреВрдг рдЕрд╕рд▓реЗрд▓реНрдпрд╛ commands рдирд╛ AWS CLI (рдХрд┐рдВрд╡рд╛ Terraform, psql, тАж) рдЖрдгрд┐ credentials рд▓рд╛рдЧрддрд╛рдд, рдЖрдгрд┐ рддреНрдпрд╛рдВрдЪрд╛ рдЦрд░реНрдЪ рдпреЗрдК рд╢рдХрддреЛ.

ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ

рд╢рд╛рд│реЗрд▓рд╛ рдирд╡реА рдЗрдорд╛рд░рдд рд╣рд╡реА рдЖрд╣реЗ. рдореБрдЦреНрдпрд╛рдзреНрдпрд╛рдкрд┐рдХрд╛ рдХрддрд░рд┐рдирд╛ рдирд┐рдпреЛрдЬрди рдХрд╛рд░реНрдпрд╛рд▓рдпрд╛рдд рдпреЗрддреЗ рдЖрдгрд┐ рдореНрд╣рдгрддреЗ: "рдЖрдореНрд╣рд╛рд▓рд╛ рдПрдХ рдирд╡рд╛ рд╣реЙрд▓ рд╣рд╡рд╛ рдЖрд╣реЗ."

рдирд┐рдпреЛрдЬрди рдХрд╛рд░реНрдпрд╛рд▓рдп рджреАрдкрд┐рдХрд╛ рдЪрд╛рд▓рд╡рддреЗ. рддреА рдкреЗрдиреНрд╕рд┐рд▓ рдЙрдЪрд▓реВрди рд▓рдЧреЗрдЪ рдЪрд┐рддреНрд░ рдХрд╛рдврд╛рдпрд▓рд╛ рд╕реБрд░реБрд╡рд╛рдд рдХрд░рдд рдирд╛рд╣реА. рддреА рдПрдХ рдлреЙрд░реНрдо ЁЯУЛ рдЙрдЪрд▓рддреЗ рдЖрдгрд┐ рд╡рд┐рдЪрд╛рд░рддреЗ:

60 рдореБрд▓рд╛рдВрд╕рд╛рдареАрдЪрд╛ рд╣реЙрд▓ рдЖрдгрд┐ 6,000 рдореБрд▓рд╛рдВрд╕рд╛рдареАрдЪрд╛ рд╣реЙрд▓ рдпрд╛ рд╡реЗрдЧрд╡реЗрдЧрд│реНрдпрд╛ рдЗрдорд╛рд░рддреА рдЖрд╣реЗрдд. рджреАрдкрд┐рдХрд╛рдиреЗ рдЖрдзреА рдХрд╛рдврд▓реЗ рдЖрдгрд┐ рдирдВрддрд░ рд╡рд┐рдЪрд╛рд░рд▓реЗ, рддрд░ рддреА рдЪреБрдХреАрдЪреА рдЗрдорд╛рд░рдд рдХрд╛рдвреЗрд▓ тАФ рдЖрдгрд┐ рднрд┐рдВрддреА рдЙрднреНрдпрд╛ рд░рд╛рд╣реАрдкрд░реНрдпрдВрдд рдХреЛрдгрд╛рдЪреНрдпрд╛рд╣реА рд▓рдХреНрд╖рд╛рдд рдпреЗрдгрд╛рд░ рдирд╛рд╣реА.

рдЖрдкрд▓рд╛ "рд╣реЙрд▓" рдореНрд╣рдгрдЬреЗ рдПрдХ app: рдПрдХ рд╕реВрдЪрдирд╛ рдлрд▓рдХ, рдЬрд┐рдереЗ рд╢рд┐рдХреНрд╖рд┐рдХрд╛ рд╕реВрдЪрдирд╛ post рдХрд░рддрд╛рдд рдЖрдгрд┐ 5 million рдкрд╛рд▓рдХ рддреНрдпрд╛ рд╡рд╛рдЪрддрд╛рдд. рдирд┐рдпреЛрдЬрди рдХрд╛рд░реНрдпрд╛рд▓рдп рдЖрдзреА рдлреЙрд░реНрдо рднрд░рддреЗ.

ЁЯЧ║я╕П рдЖрдХреГрддреА

flowchart LR
    brief["ЁЯУЭ the brief<br/>'a notice board app<br/>for 5 million parents'"]
    q["тЭУ clarifying questions<br/>how many schools? peak time?<br/>data kept how long?"]
    subgraph sheet["ЁЯУЛ the requirements sheet"]
      f["тЬЕ functional<br/>post ┬╖ read ┬╖ notify"]
      nf["ЁЯУП non-functional<br/>p99 < 200 ms ┬╖ 99.9%<br/>100 reads : 1 post ┬╖ never lost"]
      c["ЁЯз▒ constraints<br/>team of 4 ┬╖ AWS ┬╖ Marathi + English<br/>few thousand $/month ┬╖ 3 months"]
      o["ЁЯЪл out of scope<br/>chat ┬╖ payments ┬╖ video"]
    end
    next["ЁЯзо lesson 02<br/>turn it into numbers"]
    brief --> q --> sheet --> next

ЁЯЧ║я╕П рдХрд╛рдврд▓реЗрд▓реА рдЖрд╡реГрддреНрддреА + рдПрдХ lab: https://school-edh.pages.dev/system-design/lesson-diagrams.html#l01

тЭУ рдХрд╛рдп

ЁЯдФ рдХрд╛

рдХрд╛рд░рдг рдкреБрдврдЪрд╛ рдкреНрд░рддреНрдпреЗрдХ рдирд┐рд░реНрдгрдп рдпрд╛ рдХрд╛рдЧрджрд╛рд╡рд░ рдЕрд╡рд▓рдВрдмреВрди рдЕрд╕рддреЛ. рдкреНрд░рддреНрдпреЗрдХ post рдорд╛рдЧреЗ 100 reads рдореНрд╣рдгрдЬреЗ "reads cache рдХрд░рд╛" (рдзрдбрд╛ 05). "рдХрдзреАрд╣реА рд╣рд░рд╡реВ рдирдпреЗ" рдореНрд╣рдгрдЬреЗ "posted" рджрд╛рдЦрд╡рдгреНрдпрд╛рдЖрдзреА database рдордзреНрдпреЗ рдЯрд┐рдХрд╛рдК write, рдЖрдгрд┐ events рд╕рд╛рдареА outbox (рдзрдбрд╛ 08). 4 рдЬрдгрд╛рдВрдЪреА team рдореНрд╣рдгрдЬреЗ рдмрд╛рд░рд╛ services рдирд╛рд╣реА, рддрд░ рдПрдХ modular monolith (рдзрдбрд╛ 09). рдорд╣рд┐рдиреНрдпрд╛рд▓рд╛ рдХрд╛рд╣реА рд╣рдЬрд╛рд░ dollars рдореНрд╣рдгрдЬреЗ 200 servers рд▓рд╛рдЧрдгрд╛рд░реА рд░рдЪрдирд╛ рдмрд╛рдж. рдХрд╛рдЧрджрд╛рд╡рд░рдЪреА рдПрдХ рдУрд│ рдмрджрд▓рд╛ рдЖрдгрд┐ рдпреЛрдЧреНрдп рд░рдЪрдирд╛ рдмрджрд▓рддреЗ. рдореНрд╣рдгреВрдирдЪ рдХрд╛рдЧрдж рдЖрдзреА рдпреЗрддреЛ.

ЁЯОд рдореБрд▓рд╛рдЦрддреАрдд vs ЁЯПв рдкреНрд░рддреНрдпрдХреНрд╖ рдХрд╛рдорд╛рдд

ЁЯОд design рдореБрд▓рд╛рдЦрдд (45 рдорд┐рдирд┐рдЯреЗ) ЁЯПв рдкреНрд░рддреНрдпрдХреНрд╖ рдХрд╛рдо (рдЖрдард╡рдбреЗ)
рдкреНрд░рд╢реНрдирд╛рдВрдЪреА рдЙрддреНрддрд░реЗ рдХреЛрдг рджреЗрддреЗ рдореБрд▓рд╛рдЦрдд рдШреЗрдгрд╛рд░реЗ, рдПрдХрд╛ рд╡рд╛рдХреНрдпрд╛рдд product owners, рд╢рд┐рдХреНрд╖рд┐рдХрд╛, рдкрд╛рд▓рдХ, рд╡рдХреАрд▓, finance
рддреБрдореНрд╣реА рдХрд┐рддреА рд╡реЗрд│ рдШрд╛рд▓рд╡рддрд╛ 5 рдорд┐рдирд┐рдЯреЗ тАФ рдордЧ рдкреБрдвреЗ рдЬрд╛ рджрд┐рд╡рд╕ тАФ рдЖрдгрд┐ рдХрд╛рдЧрдж рдирдВрддрд░ рдмрджрд▓рддреЛ
рдЖрдХрдбреЗ рдЧреЛрд▓ рдЖрдгрд┐ рдорд┐рд│реВрди рдард░рд╡рд▓реЗрд▓реЗ ("рд╕рдордЬрд╛ 5M users") logs, рд╕рд░реНрд╡реЗрдХреНрд╖рдгреЗ, рддрд╢рд╛рдЪ app рдордзреВрди рдореЛрдЬрд▓реЗрд▓реЗ
рддреЗ рдХрд╛рдп рддрдкрд╛рд╕рддрд╛рдд рддреБрдореНрд╣реА рдХрд╛рдврдгреНрдпрд╛рдЖрдзреА рд╡рд┐рдЪрд╛рд░рддрд╛ рдХрд╛, рдЖрдгрд┐ trade-offs рд╕рд╛рдВрдЧрддрд╛ рдХрд╛ launch рд╡реЗрд│реА тАФ рдЖрдгрд┐ рдирдВрддрд░рд╣реА тАФ system рдХрд╛рдЧрджрд╛рд╡рд░рдЪреНрдпрд╛ рдЧрд░рдЬрд╛ рдкреВрд░реНрдг рдХрд░рддреЗ рдХрд╛
рдлрд▓рд┐рдд whiteboard рд╡рд░рдЪреА рдЖрдХреГрддреА рд▓рд┐рд╣рд┐рд▓реЗрд▓реЗ design doc + ADRs (рдзрдбрд╛ 16), рдЗрддрд░рд╛рдВрдиреА рддрдкрд╛рд╕рд▓реЗрд▓реЗ

рджреЛрдиреНрд╣реАрдХрдбреЗ рд╕рд╡рдп рдПрдХрдЪ: рд╡рд┐рдЪрд╛рд░рд╛, рд▓рд┐рд╣реВрди рдареЗрд╡рд╛, рдордЧ рдХрд╛рдврд╛.

ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)

design/demo.py рдордзреАрд▓ requirements() рд╕реВрдЪрдирд╛ рдлрд▓рдХрд╛рдЪрд╛ рдХрд╛рдЧрдж рдЫрд╛рдкрддреЗ: рддреАрди functional рдУрд│реА, рдЖрдХрдбреНрдпрд╛рдВрд╕рд╣ рдЪрд╛рд░ non-functional рдУрд│реА, рддреАрди рдорд░реНрдпрд╛рджрд╛, рдХрдХреНрд╖реЗрдмрд╛рд╣реЗрд░рдЪреА рдпрд╛рджреА рдЖрдгрд┐ рд╡рд┐рдЪрд╛рд░рд╛рдпрдЪреЗ рдкреНрд░рд╢реНрди. рдордЧ рдзрдбрд╛ 02 рдпрд╛ рдХрд╛рдЧрджрд╛рд╡рд░рдЪреЗ рдЖрдХрдбреЗ design/blocks.py рдордзреАрд▓ estimate() рд▓рд╛ рджреЗрддреЛ. рдЦрд╛рд▓рдЪреНрдпрд╛ snippet рдордзреНрдпреЗ рддреБрдореНрд╣реА рджреЛрди рд╕реНрдкрд╖реНрдЯреАрдХрд░рдгрд╛рдЪреНрдпрд╛ рдкреНрд░рд╢реНрдирд╛рдВрдЪреА рдЙрддреНрддрд░реЗ рд╡реЗрдЧрд╡реЗрдЧрд│реА рджреЗрддрд╛ тАФ рдкреНрд░рддреНрдпреЗрдХ рд╕реВрдЪрдиреЗрд▓рд╛ рдХрд┐рддреА reads? рдЖрдгрд┐ рд╕реВрдЪрдирд╛ рдХрд┐рддреА рдХрд╛рд│ рдареЗрд╡рд╛рдпрдЪреНрдпрд╛? тАФ рдЖрдгрд┐ system рдЪрд╛ рдЖрдХрд╛рд░ рдХрд╕рд╛ рдмрджрд▓рддреЛ рддреЗ рдкрд╛рд╣рддрд╛.

ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛

python3 design/demo.py requirements
python3 - <<'EOF'
import sys; sys.path.insert(0, "design"); from blocks import estimate
for ratio in (10, 100, 1000):
    e = estimate(5_000_000, 0.2, ratio, 2_000)
    print(f"reads per notice {ratio:>4} тЖТ peak {e['peak_rps']:>6,} req/s ┬╖ {e['servers']:>3} servers")
for years in (1, 5, 10):
    print(f"notices kept {years:>2} y тЖТ {estimate(5_000_000, 0.2, 100, 2_000, years=years)['storage_tb']:>5} TB")
EOF

тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ

requirements рдЫрд╛рдкрддреЗ:

тФАтФА the brief: 'build a notice board app for 5 million parents'. Before drawing a box, write the sheet:
   functional     a teacher posts a notice to a class
                  a parent reads the notices of their children's classes
                  a parent gets a notification for urgent notices
   non-functional read p99 < 200 ms ┬╖ post p99 < 500 ms
                  99.9% available
                  reads outnumber posts ~100 : 1
                  a notice must never be lost once 'posted' is shown
   constraints    team of 4 ┬╖ AWS ┬╖ Marathi + English
                  budget: a few thousand dollars a month
                  launch in 3 months
   out of scope (say it!): chat, payments, video ┬╖ questions to ask: how many schools? peak time? data kept how long?

рддреБрдордЪрд╛ snippet рдЫрд╛рдкрддреЛ:

reads per notice   10 тЖТ peak    382 req/s ┬╖   2 servers
reads per notice  100 тЖТ peak  3,507 req/s ┬╖  12 servers
reads per notice 1000 тЖТ peak 34,757 req/s ┬╖ 116 servers
notices kept  1 y тЖТ  2.19 TB
notices kept  5 y тЖТ 10.95 TB
notices kept 10 y тЖТ  21.9 TB

ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ

рдПрдХрд╛ рд╕реНрдкрд╖реНрдЯреАрдХрд░рдгрд╛рдЪреНрдпрд╛ рдкреНрд░рд╢реНрдирд╛рдЪреЗ рдПрдХ рдЙрддреНрддрд░ рд░рдЪрдиреЗрд▓рд╛ 2 servers рд╡рд░реВрди 116 рд╡рд░ рдиреЗрддреЗ. рджреБрд╕рд░реЗ рдЙрддреНрддрд░ storage рджреБрдкреНрдкрдЯ рдХрд░рддреЗ. рддреЗрдЪ рдХрд╛рдо, рддреАрдЪ app рдЪреА рдХрд▓реНрдкрдирд╛ тАФ рдкрдг рд╡реЗрдЧрд│реА рдЗрдорд╛рд░рдд. рдореНрд╣рдгреВрдирдЪ рдирд┐рдпреЛрдЬрди рдХрд╛рд░реНрдпрд╛рд▓рдп рдХрд╛рдврдгреНрдпрд╛рдЖрдзреА рд╡рд┐рдЪрд╛рд░рддреЗ: рдЪрд┐рддреНрд░ рдирд╡реНрд╣реЗ, рдХрд╛рдЧрдж рдЖрдХрд╛рд░ рдард░рд╡рддреЛ.

тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛

ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд

рдкреНрд░рддреНрдпрдХреНрд╖ рдХрд╛рдорд╛рдд рд╣рд╛ рдХрд╛рдЧрдж design document рдЪреЗ рдкрд╣рд┐рд▓реЗ рдкрд╛рди рдЕрд╕рддреЛ, рдХреЛрдгреАрд╣реА рдмрд╛рдВрдзрд╛рдпрд▓рд╛ рд╕реБрд░реБрд╡рд╛рдд рдХрд░рдгреНрдпрд╛рдЖрдзреА рддрдкрд╛рд╕рд▓реЗрд▓реЗ. рдирд┐рдпреЛрдЬрди рдХрд╛рд░реНрдпрд╛рд▓рдп repo рдордзреНрдпреЗ рдареЗрд╡рддреЗ рддреА рдЫреЛрдЯреА рдЖрд╡реГрддреНрддреА:

# Notice board тАФ requirements (v1, 2026-09)
## Functional
- F1 a teacher posts a notice to a class (text, optional photo, urgent flag)
- F2 a parent reads the notices of their children's classes, newest first
- F3 a parent gets a push/SMS for urgent notices
## Non-functional
- read p99 < 200 ms, post p99 < 500 ms (measured at the load balancer)
- 99.9% monthly availability; RPO 0 for posted notices, RTO 1 hour
- 5M parents, ~1M notices/day, ~100 reads per notice, peak ├Ч3 at 7тАУ9 am
## Constraints
- team of 4 ┬╖ AWS ap-south-1 (children's data stays in India) ┬╖ Marathi + English
- budget ~$3,000/month ┬╖ launch in 3 months
## Out of scope (v1)
- chat, payments, video
## Open questions
- how many schools in year 1? ┬╖ how long are notices kept? ┬╖ may parents reply?

On a real account тАФ рдХрд╛рд╣реА рдорд░реНрдпрд╛рджрд╛ рдкрдХреНрдХреНрдпрд╛ рдЕрд╕рддрд╛рдд, рдЬреНрдпрд╛ рд░рдЪрдирд╛ рдХрд░рдгреНрдпрд╛рдЖрдзреА рддреБрдореНрд╣реА рдкрд╛рд╣реВ рд╢рдХрддрд╛. рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, рддреБрдордЪреНрдпрд╛ account рдордзреАрд▓ Amazon SNS рдЪреА SMS рдЦрд░реНрдЪ рдорд░реНрдпрд╛рджрд╛ (5M рддрд╛рддрдбреАрдЪреЗ SMS рд▓рд╣рд╛рди default рдорд░реНрдпрд╛рджрд╛ рдореЛрдбрддреАрд▓):

aws sns get-sms-attributes --attributes MonthlySpendLimit
aws service-quotas list-service-quotas --service-code sns --query 'Quotas[].{name:QuotaName,value:Value}'

ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: рдмрд╣реБрддреЗрдХ рдЕрдкрдпрд╢реА projects рдПрдЦрд╛рджреНрдпрд╛ рдХрдареАрдг algorithm рдореБрд│реЗ рдЕрдкрдпрд╢реА рдЭрд╛рд▓реЗ рдирд╛рд╣реАрдд. рддреНрдпрд╛рдВрдиреА рдЪреБрдХреАрдЪреА рдЧреЛрд╖реНрдЯ рдмрд╛рдВрдзрд▓реА, рдХрд┐рдВрд╡рд╛ рдмрд░реЛрдмрд░ рдЧреЛрд╖реНрдЯ рдЪреБрдХреАрдЪреНрдпрд╛ рдЖрдХрдбреНрдпрд╛рдВрд╕рд╛рдареА рдмрд╛рдВрдзрд▓реА. System рдорд╛рдЧрдгрд╛рд▒реНрдпрд╛ рд▓реЛрдХрд╛рдВрдиреА рдорд╛рдиреНрдпрддрд╛ рджрд┐рд▓реЗрд▓рд╛ рдПрдХрд╛ рдкрд╛рдирд╛рдЪрд╛ рдХрд╛рдЧрдж рд╣рд╛ рд╕рд░реНрд╡рд╛рдд рд╕реНрд╡рд╕реНрдд рдЙрдкрд╛рдп рдЖрд╣реЗ.

тПня╕П рдкреБрдвреЗ

рдХрд╛рдЧрдж рдореНрд╣рдгрддреЛ "5 million рдкрд╛рд▓рдХ" рдЖрдгрд┐ "рдкреНрд░рддреНрдпреЗрдХ рд╕реВрдЪрдиреЗрд▓рд╛ 100 reads". рдореНрд╣рдгрдЬреЗ рд╕реЗрдХрдВрджрд╛рд▓рд╛ рдХрд┐рддреА requests? рдХрд┐рддреА terabytes? рдХрд┐рддреА servers? рдирд┐рдпреЛрдЬрди рдХрд╛рд░реНрдпрд╛рд▓рдп рдЖрдХрдбреЗрдореЛрдб рдХрд░рддреЗ.

git checkout lesson-02-capacity

ЁЯУЛ Lesson 01 тАФ Requirements & constraints: the planning office asks before it draws

ЁЯУН You are here: Lesson 01 of 18 ┬╖ Next: lesson-02-capacity


ЁЯУж What's in this branch

The one habit this whole course is built on: before you draw a single box, write down what the system must do, how well, and within which limits. The brief is one line тАФ "build a notice board app for 5 million parents" тАФ and in this lesson it becomes a sheet with four parts: functional needs, non-functional needs with numbers, constraints and out of scope, plus the questions you ask the person who gave you the brief. Real files you will use all the way through:

ЁЯОТ Before you start: you need Python 3 and nothing else тАФ no cloud account, no pip install. The files hold teaching models with round example numbers (500 requests a second per server, 2 KB per notice, a peak of 3├Ч). The method matters more than the digits. Commands marked on a real account need the AWS CLI (or Terraform, psql, тАж) and credentials, and they can cost money.

ЁЯзТ Explain like I'm 5

The school wants a new building. The head teacher, Katrina, walks into the planning office and says: "We need a new hall."

Dipika runs the planning office. She does not pick up a pencil and start drawing. She picks up a form ЁЯУЛ and asks:

A hall for 60 children and a hall for 6,000 are different buildings. If Dipika draws first and asks later, she draws the wrong building тАФ and nobody notices until the walls are up.

Our "hall" is an app: a notice board where teachers post notices and 5 million parents read them. The planning office fills in the form first.

ЁЯЧ║я╕П Diagram

flowchart LR
    brief["ЁЯУЭ the brief<br/>'a notice board app<br/>for 5 million parents'"]
    q["тЭУ clarifying questions<br/>how many schools? peak time?<br/>data kept how long?"]
    subgraph sheet["ЁЯУЛ the requirements sheet"]
      f["тЬЕ functional<br/>post ┬╖ read ┬╖ notify"]
      nf["ЁЯУП non-functional<br/>p99 < 200 ms ┬╖ 99.9%<br/>100 reads : 1 post ┬╖ never lost"]
      c["ЁЯз▒ constraints<br/>team of 4 ┬╖ AWS ┬╖ Marathi + English<br/>few thousand $/month ┬╖ 3 months"]
      o["ЁЯЪл out of scope<br/>chat ┬╖ payments ┬╖ video"]
    end
    next["ЁЯзо lesson 02<br/>turn it into numbers"]
    brief --> q --> sheet --> next

ЁЯЧ║я╕П Drawn version + a lab: https://school-edh.pages.dev/system-design/lesson-diagrams.html#l01

тЭУ What

ЁЯдФ Why

Because every later decision depends on this sheet. 100 reads for every post means "cache the reads" (lesson 05). "Never lost" means a durable database write before "posted" is shown, and an outbox for the events (lesson 08). A team of 4 means one modular monolith, not twelve services (lesson 09). A few thousand dollars a month rules out a design that needs 200 servers. Change one line on the sheet and the right design changes. That is why the sheet comes first.

ЁЯОд In an interview vs ЁЯПв in real work

ЁЯОд A design interview (45 minutes) ЁЯПв Real work (weeks)
Who answers the questions the interviewer, in one sentence product owners, teachers, parents, lawyers, finance
How long you spend 5 minutes тАФ then move on days тАФ and the sheet changes later
Numbers round and invented together ("say 5M users") measured from logs, surveys, a similar app
What they judge that you ask before you draw, and name trade-offs that the system meets the sheet at launch тАФ and after
Output a whiteboard diagram a written design doc + ADRs (lesson 16), reviewed by others

The habit is the same in both: ask, write it down, then draw.

ЁЯФз How (in this repo)

requirements() in design/demo.py prints the notice board's sheet: three functional lines, four non-functional lines with numbers, three constraints, the out-of-scope list and the questions to ask. Lesson 02 then feeds the numbers on this sheet into estimate() in design/blocks.py. In the snippet below you answer two clarifying questions differently тАФ how many reads per notice? and how long do we keep notices? тАФ and watch the size of the system change.

ЁЯзк Try it

python3 design/demo.py requirements
python3 - <<'EOF'
import sys; sys.path.insert(0, "design"); from blocks import estimate
for ratio in (10, 100, 1000):
    e = estimate(5_000_000, 0.2, ratio, 2_000)
    print(f"reads per notice {ratio:>4} тЖТ peak {e['peak_rps']:>6,} req/s ┬╖ {e['servers']:>3} servers")
for years in (1, 5, 10):
    print(f"notices kept {years:>2} y тЖТ {estimate(5_000_000, 0.2, 100, 2_000, years=years)['storage_tb']:>5} TB")
EOF

тЬЕ Verify тАФ what you should see

requirements prints:

тФАтФА the brief: 'build a notice board app for 5 million parents'. Before drawing a box, write the sheet:
   functional     a teacher posts a notice to a class
                  a parent reads the notices of their children's classes
                  a parent gets a notification for urgent notices
   non-functional read p99 < 200 ms ┬╖ post p99 < 500 ms
                  99.9% available
                  reads outnumber posts ~100 : 1
                  a notice must never be lost once 'posted' is shown
   constraints    team of 4 ┬╖ AWS ┬╖ Marathi + English
                  budget: a few thousand dollars a month
                  launch in 3 months
   out of scope (say it!): chat, payments, video ┬╖ questions to ask: how many schools? peak time? data kept how long?

Your snippet prints:

reads per notice   10 тЖТ peak    382 req/s ┬╖   2 servers
reads per notice  100 тЖТ peak  3,507 req/s ┬╖  12 servers
reads per notice 1000 тЖТ peak 34,757 req/s ┬╖ 116 servers
notices kept  1 y тЖТ  2.19 TB
notices kept  5 y тЖТ 10.95 TB
notices kept 10 y тЖТ  21.9 TB

ЁЯПБ What you just proved

One answer to one clarifying question moves the design from 2 servers to 116. Another doubles the storage. Same brief, same app idea тАФ a different building. That is why the planning office asks before it draws: the sheet, not the drawing, decides the shape.

тЪая╕П Common mistakes

ЁЯПн In production

In real work the sheet is the first page of a design document, reviewed before anyone builds. A short version the planning office keeps in the repo:

# Notice board тАФ requirements (v1, 2026-09)
## Functional
- F1 a teacher posts a notice to a class (text, optional photo, urgent flag)
- F2 a parent reads the notices of their children's classes, newest first
- F3 a parent gets a push/SMS for urgent notices
## Non-functional
- read p99 < 200 ms, post p99 < 500 ms (measured at the load balancer)
- 99.9% monthly availability; RPO 0 for posted notices, RTO 1 hour
- 5M parents, ~1M notices/day, ~100 reads per notice, peak ├Ч3 at 7тАУ9 am
## Constraints
- team of 4 ┬╖ AWS ap-south-1 (children's data stays in India) ┬╖ Marathi + English
- budget ~$3,000/month ┬╖ launch in 3 months
## Out of scope (v1)
- chat, payments, video
## Open questions
- how many schools in year 1? ┬╖ how long are notices kept? ┬╖ may parents reply?

On a real account тАФ some constraints are hard limits you can look up before you design. For example, the SMS spending limit for Amazon SNS in your account (5M urgent SMS would break a small default limit):

aws sns get-sms-attributes --attributes MonthlySpendLimit
aws service-quotas list-service-quotas --service-code sns --query 'Quotas[].{name:QuotaName,value:Value}'

ЁЯПн Why this matters in production: most failed projects did not fail on a hard algorithm. They built the wrong thing, or the right thing for the wrong numbers. A one-page sheet, signed off by the people who asked for the system, is the cheapest fix there is.

тПня╕П Next

The sheet says "5 million parents" and "100 reads per notice". How many requests a second is that? How many terabytes? How many servers? The planning office does the numbers.

git checkout lesson-02-capacity
тЖР Course homeall lessonsNext тЖТcapacity

This page is the lesson's README from the lesson-01-requirements branch, shown here so the whole School stays on one site. Code files open on GitHub at the same branch.