Chaya·Edu EDU.CHAYA.DEV

Sessions 21–22 · Notes 12

The Park, Written Down

All term you have built the park by hand — clicking consoles, running commands, remembering settings. This week the whole park becomes text: a recipe a robot can rebuild from scratch, identically, every time — and a conveyor belt that ships your code the same careful way on every push.

Mon & Wed 16 & 18 Nov 2026 16:00–17:50 Google Meet Instructor Prof. Yair Chaya Reading ~20 min

01The Snowflake Problem

Last week ended with a promise: the whole park, written down. Every bucket, queue, and database you have rented this term, declared in files you can version, review, and rebuild from scratch. Here is why that promise matters enough to get its own week.

Picture the end of this semester. Your project works. It works because, over ten weeks, you clicked through consoles, ran commands, set permissions, picked regions, and tweaked settings — hundreds of small decisions, made one at a time, recorded nowhere. Now the horror story, and it happens somewhere every single year: the demo works on your account, and nobody — including you, three weeks from now — can build it again. Which setting made the queue finally connect? Was the bucket public or private? Why does it break on a fresh account? Nobody knows. The knowledge isn’t in a file. It’s in the park.

This style of operating has a name — click-ops, infrastructure assembled by clicking — and what it produces has a better one: the snowflake server. Every hand-built machine is unique, like a snowflake: shaped by every click and hotfix that ever touched it, impossible to copy exactly. And like a snowflake, it melts. The account closes, the region has a bad day, someone deletes the wrong thing — and the only copy of ten weeks of decisions is gone. You didn’t lose a server. You lost the recipe you never wrote down.

So here is the week’s whole idea, in one question: what if the park were a recipe a robot could cook from scratch — every time, identically? Not instructions in your head. A plain text file that is the park, the way sheet music is the song. That idea is called infrastructure as code — IaC — and if it sounds familiar, it should: your Project 3, due this week, has been making you live it.

Plate 1.1 — The snowflake vs. the recipeHand-built once · rebuildable forever
Left, a hand-built park full of question marks whose settings live in one person's head, with a melting snowflake; right, a short text recipe handed to a robot that builds two identical parks, one on Friday and one on Monday THE HAND-BUILT PARK — A SNOWFLAKE ? ? ? built by clicks, Sep → Nov settings: in Sam’s head. Sam graduates in May. unique like a snowflake — and it melts like one too works on YOUR account. nobody can rebuild it. including you. THE PARK AS A RECIPE main.tf plain text. the whole park. the robot built Friday rebuilt Monday — identical if you can’t rebuild it from a file, you don’t own a system — you’re just standing near one

02The Recipe Idea — Say What, Not How

How do you write a park down? Your first instinct is a to-do list: create the bucket, then create the queue, then resize the database… That style — a list of steps — is called imperative, and it’s brittle, because a step list only works if you know exactly where you’re starting from. Run it on a half-built park and step one fails: the bucket already exists.

Infrastructure as code uses the other style, and it’s the one a recipe card uses. A recipe card doesn’t say “walk to the fridge.” It says what the dish is: this much flour, this many eggs, an oven at this temperature. You write down what the finished park looks like — one bucket, one queue, one database this size, in this region — and the robot works out the steps. That style is called declarative: you declare the destination; the robot plans the route from wherever it happens to be standing.

And the robot has exactly one move, repeated forever: compare, then fix the difference. It looks at the recipe — the desired state — looks at the real park — the actual state — and does only whatever closes the gap. Queue missing? Create it. Database the wrong size? Resize it. Nothing out of place? Do nothing at all. You have met this move twice already. It is Notes 08’s manager — you wrote “three copies of the web pod, always” and the manager made it true, forever. And it is Notes 11’s thermostat: SET to 68, not raise-by-3. Because the recipe says what the park is, not what to add, running it twice doesn’t build two parks. The second run compares, finds no difference, and shrugs. The recipe is idempotent by construction — last week’s hero word, back on day one of the job.

Plate 2.1 — The robot’s one moveCompare desired to actual · fix the difference · repeat
A recipe listing the desired park on the left and the actual park on the right, with a robot in the middle reading both, producing a diff of create queue and resize database, and applying the fix to the park; a loop caption reads compare, fix, compare, no changes THE RECIPE — DESIRED bucket ✓ queue ✓ database size L web servers × 2 a text file. nothing more. THE PARK — ACTUAL bucket ✓ queue missing database size M web servers × 2 what actually exists right now reads the recipe looks at the park THE DIFFERENCE + create queue ~ resize database M → L apply — fix ONLY the difference compare → fix → compare → “no changes.” Notes 08’s thermostat, pointed at everything you rent — run it twice, still one park

03Terraform, Concretely

The robot has a name: Terraform, the most widely used of these tools, and the one on your Project 3. (Each provider also sells a house brand — CloudFormation on AWS, and friends — same idea, one landlord only. Terraform speaks to all of them.) You write the recipe in a little language called HCL, built to be read by humans first. Here is a real, complete recipe — the shop’s photo bucket and Notes 11’s receipt queue, written down:

main.tf — the whole recipe. plain text, in your repo.
provider "aws" {            # which landlord we rent from
  region = "us-east-1"      # and which of their parks
}

resource "aws_s3_bucket" "photos" {  # “one bucket must exist”
  bucket = "ai255-shop-photos"         # its (globally unique) name
}

resource "aws_sqs_queue" "receipts" { # “one queue must exist”
  name = "receipt-notes"               # Notes 11’s notes-on-the-door
}

Read it out loud and notice what it doesn’t say: no “first,” no “then,” no “click here.” Each resource block is one sentence of the recipe — a thing of this kind, with these settings, must exist. A dozen-odd lines of plain text, and they are a bucket and a queue — and your entire Project 3 is the same move: the park you built by hand in Project 1, written down as a recipe the robot can cook.

You drive the robot with three verbs, and they are the three verbs of your professional life from here on:

verb 1 · terraform plan

Show me the difference

The robot compares recipe to park and prints what it would do — “2 to add, 1 to change” — and does none of it. Plan is read-only homework. You read the diff before anything happens. Always.

verb 2 · terraform apply

Make it so

The robot does exactly what the plan showed: creates, resizes, removes — only the difference, nothing more. Run it again immediately: “No changes.” Apply is idempotent, because the recipe is a SET, not an ADD.

verb 3 · terraform destroy

Tear it all down

Every resource the robot built, removed cleanly, in the right order. This is the superpower click-ops never had — and the end of this course’s oldest bogeyman, the forgotten test instance billing quietly since March.

One more piece, and it deserves a plain paragraph because it bites real teams: the state file. It is the robot’s notebook — a file where Terraform writes down what it built last time, so that next time it knows which things in the account are its things. Lose the notebook and the robot forgets the park exists: the bucket and queue are still out there, running and billing, but the robot no longer knows it owns them — it can’t update them, and it can’t destroy them. You’d be back to cleaning up by hand.

Where the notebook lives

Not on your laptop. Real teams keep the state file in shared, durable storage — a bucket, naturally; Notes 09’s rented memory, holding the robot’s memory — with a lock on it, so two teammates’ robots can’t both rebuild the park at the same moment and trip over each other. Your Project 3 can keep it local; just know that “where does the notebook live?” is the first question every real team answers.

04The Robot, Live

Here is the whole loop as a toy you can drive. The dashed box is the recipe — edit it. The drawing is the park — it starts the way every real account starts: half hand-built, plus one mystery bucket from a March experiment that the robot’s notebook still remembers but the recipe no longer lists. Press plan and read the robot’s homework. Press apply and watch the park become the recipe. Then let the gremlin loose.

Plate 4.1 — Plan & applyInteractive · edit the recipe, plan, apply, vandalize, heal
main.tf — the recipe database: web servers: × 2
The park — actual statewhat really exists
The robot’s planread-only
+ create ~ change in place − destroy hand-made / drifted
In the park
0resources, right now
Plan pending
—+ add · ~ change · − destroy
Applies run
0park rebuilt to recipe
Drift healed
0hand-edits caught & fixed

Four experiments, in order. One: press plan, then look at the park — nothing moved. Plan never touches anything; it is the robot showing its homework, including throwing out the March mystery bucket the recipe doesn’t list. Two: press apply, then apply again — the second run says “No changes. Park matches the recipe.” One recipe, one park, no matter how many times you run it. Three: press the gremlin — it opens the console and hand-deletes something, the way a helpful teammate “just quickly fixes” production at midnight. The recipe didn’t change, so the next plan catches the gap — that gap is called drift — and apply heals it. Four: destroy, then plan: the robot calmly offers to rebuild the entire park from nothing. That round trip — gone, then back, identically — is the exact demonstration Project 3 asks of you this week. Now you know why.

05The Park Is Text Now — Everything Git Does, the Park Gets

Stop and notice what quietly happened: the park is now a text file in a repository. That sentence is doing more work than it looks like, because every tool you already use on code now works on infrastructure, for free.

History. “Who changed the database size, and when, and why?” used to be an archaeology project through console audit screens. Now it’s git log: a commit, with a name, a date, and a message, for every change the park has ever had.

Review. An infrastructure change arrives as a pull request, and a teammate reads the diff before the robot runs it. “You’re opening that bucket to the public — on purpose?” gets asked on Tuesday in review, instead of answered in an incident report on Saturday.

Rollback. Last week a bad deploy meant someone typing from memory at 2 a.m., hoping they remembered the old settings. Now: revert the commit, apply, and the park walks backward to exactly where it was — because the recipe is the park, an old recipe is an old park, on demand.

Plate 5.1 — Commits are park statesEvery point in history is a park you can have back
A git timeline of four commits — add bucket, add queue, grow the database, and a revert — each mapping down to the park state it produces, with the revert walking the park back to the earlier database size “add photo bucket” sam · sep 14 “add receipt queue” ava · nov 9 “database M → L” sam · nov 16 · reviewed by ava “revert: M → L was too pricey” ava · nov 17 bucket the park, sep 14 bucket · queue database M the park, nov 9 bucket · queue database L the park, nov 16 bucket · queue database M again the park, nov 17 revert the file + apply = the park walks back. nobody types from memory at 2 a.m. history, review, rollback — everything git gave your code, the park now gets for free

06The Conveyor Belt — CI/CD

The recipe rebuilt the park. The second half of this week applies the same spirit to your code’s trip into the park — because that trip has been click-ops too. Think about how you’ve been deploying: build the image, run the tests (when you remember), push, deploy, check it. Steps in a human’s head, done slightly differently every time, with the dangerous ones skippable on exactly the days you’re rushed enough to skip them.

So write that down too. A pipeline is the deploy routine as a file in the repo: push code, and a robot runs the same steps, in the same order, every single time — build it, test it, ship it — like a factory conveyor belt that no one can absent-mindedly skip a station on. Two names cover the idea, one plain sentence each. CI — continuous integration: every push gets built and tested immediately, so a breakage is caught in minutes, by a robot, instead of days later by a confused teammate — or a customer. CD — continuous delivery: whatever passes the tests flows onward to deployment, automatically or at the press of one button, so shipping stops being an event and becomes a habit.

Pipelines are also just small recipes. Here is a real one, in the format GitHub Actions uses — a file that lives in your repo next to the code it ships:

.github/workflows/ship.yml — the conveyor belt, written down
name: ship
on: [push]                        # every push starts the belt

jobs:
  ship:
    runs-on: ubuntu-latest        # a rented, disposable machine
    steps:
      - uses: actions/checkout@v4 # station 0: fetch the code
      - run: npm install           # station 1: BUILD — assemble the parts
      - run: npm test              # station 2: TEST — red here STOPS the belt
      - run: npm run deploy        # station 3: DEPLOY — only reached on green
        if: github.ref == 'refs/heads/main'  # and only from the main branch

The line that earns its keep is the test station: a red test stops the belt, and whatever is on it never reaches production. Not “shouldn’t” — can’t. The deploy station is physically downstream of the gate. And here is where the week’s two halves click together: the belt can run terraform plan on every pull request, so an infrastructure change shows its diff right in the review — the robot’s homework, attached to the conversation, before anyone presses apply. The recipe and the belt aren’t two tools; they’re one habit. Nothing reaches production except through a file that was reviewed.

Plate 6.1 — The beltInteractive · push a commit, watch the stations — red stops the belt
Build

the robot assembles the parts

idle
Test

the gate — red stops the belt

idle
Deploy

ship to production

idle
Pushes
0belt runs started
Caught at the gate
0broken commits stopped
Shipped
0reached production
Bad code shipped
0the belt never lets one by

Push the broken commit a few times and watch the right-hand counter. It will read zero today, zero tomorrow, zero forever — that zero is the entire sales pitch. The belt isn’t about speed, though you get speed. It’s that the careful path and the lazy path become the same path, so being careful stops costing discipline. This is how every real team you’ll join ships every service we have studied this term.

07Why This Matters — and Where It Honestly Stops

Put the two halves together and some very old problems just… dissolve.

Disaster recovery. Notes 10 taught you that regions die — not often, but definitely. For the click-ops team, a dead region means reconstructing ten months of clicks from memory, under pressure, on the worst day of the year. For the recipe team it means: change region = "us-east-1" to another one, run apply, and go get coffee while the robot rebuilds the park somewhere the ground isn’t on fire.

“Works on my machine” dies. Dev, staging, and production stop being three cousins who drifted apart and become three runs of the same recipe — identical by construction. A bug in staging is now a bug in production’s exact twin, which is the only kind of staging worth paying for.

Onboarding and audit. The new teammate’s first day used to be a week of “ask Sam.” Now it’s clone the repo, read the recipe, run one command — and when someone asks “who can reach the database, and since when?” (Week 6’s question), the answer is a file, with a history, instead of a shrug.

Never change the park by hand — change the recipe

The park is a printout; the recipe is the document. Edit a printout and the next print erases your pen marks — that’s drift, and you watched the robot do exactly that to the gremlin. One habit, from today: if it’s worth changing, it’s worth changing in the file.

The honest limits

Terraform will not save you from a bad recipe: declare a wide-open bucket and the robot will build you a perfectly reproducible wide-open bucket, every time, in every region — garbage in, identical garbage out. It cannot stop a teammate from click-opsing behind its back; it can only catch the drift on the next plan — which is why real teams run plan on a schedule, as a smoke detector. And the state file is real state with real failure modes (lose it, corrupt it, let two applies race) — which is why it lives in shared storage, locked. The robot is an amplifier, not an adult. The judgment stays your job.

08Self-Check

Six quick questions. Pick an answer to see whether you’re right and why. Nothing is recorded; this is for you.

Score 0 / 0

09Before Session 23 — November 23

A due date, a new spec, and two toys to drive. The list remembers your progress on this device.

Bring to Session 23

One sentence naming a thing in your own project that still exists only as clicks — something no file describes — and what it would take to write it down. Then next week, the last big question of the term: the park is built, rebuilt, and shipping on every push… but how do you know it’s healthy? Gauges, logs, and alarms — and the people who get woken up at 3 a.m. when one goes off. Observability.

10Key Terms

Infrastructure as code (IaC)
The park as a text file: everything you rent, declared in files you can version, review, and rebuild from.
Click-ops
Building infrastructure by clicking consoles. Fast today, unrepeatable forever.
Snowflake server
A hand-built machine: unique like a snowflake, shaped by every click that ever touched it — and it melts like one.
Declarative
Say what the finished park IS; the robot plans the steps. The recipe card, not the to-do list.
Imperative
A list of steps. Brittle, because steps only work from a known starting point.
Desired state / actual state
The recipe vs. the real park. The robot’s one move: compare them, fix the difference.
Drift
The park no longer matching the recipe, usually because someone changed it by hand. Caught on the next plan.
Terraform
The most widely used IaC robot; speaks to every major landlord. Provider house brands (CloudFormation etc.) do the same job for one.
HCL
The little language Terraform recipes are written in — built to be read by humans first.
plan
“Show me the difference.” Read-only: prints what would change and changes nothing. Read it before every apply.
apply
“Make it so.” Fixes only the difference. Idempotent: run twice, still one park — “No changes.”
destroy
Removes everything the robot built, cleanly, in order. The guaranteed-complete teardown click-ops never had.
State file
The robot’s notebook of what it built last time. Lose it and the robot forgets it owns the park. Keep it in shared storage, locked.
CI — continuous integration
Every push is built and tested immediately, so breakage is caught in minutes by a robot, not in days by a customer.
CD — continuous delivery
What passes the tests flows on to deployment, automatically or at one button — shipping as a habit, not an event.
Pipeline
The deploy routine as a file in the repo: build → test → deploy, same stations, same order, every push.
GitHub Actions
A common place pipelines run; the YAML file in your repo is the belt’s recipe.
Rollback
Revert the recipe, apply — the park walks back to a state it has already been in. Git’s gift to infrastructure.
Environments (dev / staging / prod)
Three runs of the same recipe instead of three drifting cousins — identical by construction.