This walks through one small, real, working piece of software, an Orders API from "what's an API?" all the way to a real bug we hit and fixed.
This is part of a hands-on course. Every module takes code that works fine as a tiny example, and shows why it breaks down once it meets the real world, then teaches the fix.
Two apps need to talk to each other. Neither can just reach inside the other and grab what it wants — so one of them opens a set of specific, agreed-upon "doors" the other is allowed to knock on.
An API is a defined way for one program to ask another to do something, or hand over data.
Think about the Uber app on your phone. It can't reach into Uber's servers directly. Instead, Uber's servers expose a fixed set of doors your phone is allowed to knock on — "get me nearby drivers," "book this ride," "cancel this ride." That whole set of doors, plus the rules for how to knock on each one, is the API.
GET /driversPOST /ridesDELETE /rides/{id}A web API is just a program sitting somewhere, waiting for requests over HTTP — the same protocol your browser uses to load any page — and answering back with data.
A microservice means building many small, independent programs instead of one giant one — each responsible for exactly one job, talking to the others only through APIs.
Orders, Payments, and Inventory all live in one codebase. They ship together and scale together — simple, until one part needs to change without the others.
Each piece is its own independent program. One going down doesn't take the rest with it. Only the piece under pressure needs to scale.
FastAPI is a Python tool that turns an ordinary function into something the internet can call, without you having to write the plumbing by hand.
@app.post("/orders") means "run this function whenever
someone POSTs here." That's the whole setup.
Before your own code runs a single line, FastAPI checks the incoming data is shaped correctly — for free.
No manual parsing of raw internet traffic — the data just arrives, already usable.
Think of this service as a reception desk. Schemas are the paperwork templates it uses to check exactly what's allowed in the door — and what goes back out.
one line item on the order
the intake form for a new order
the receipt sent back
This single decorator line is doing four separate jobs at once. Here's each one, in plain English.
"/orders"Only run this function when a request hits this exact
addressresponse_model=OrderResponseShape whatever this function returns to
match that receipt formatstatus_code=201The standard internet code meaning "something new was
successfully created"request: CreateOrderRequestThe incoming data is auto-checked and
handed to you already usableBefore Module 12, an earlier exercise hit a genuine bug — the kind every developer runs into eventually. Converting a dollar amount into cents produced the wrong number.
The test sent $19.99 and expected it to become exactly 1999 cents. Instead, it got 1998.
Why: computers store decimal numbers like 19.99 in a format that can't represent every decimal exactly — it's stored as something microscopically smaller, like 19.989999999999998. int() chops off everything after the decimal point, so that tiny error rounds down and loses a whole cent. round() rounds to the nearest whole number instead.
This is what the Orders endpoint looked like as an unfinished stub, versus the finished, working version.
If nothing was ordered, the function now stops immediately and replies with a clear error — instead of silently accepting nonsense.
Price × quantity, summed across every line — the one piece of real math this endpoint needed to do.
The finished order gets stored so it can be looked up again later.
The customer, the total, and the item count get packaged up and sent back as proof the order went through.
Nothing new conceptually here — this is the same shape of logic used throughout the whole course, just now running inside a web request.
Module 1's plain function and this module's web endpoint do the identical job. Only the wrapping around it changed.
Each test acts like a pretend user of the API, sending a request and checking exactly what comes back.
Tap any question to reveal the answer, written in plain language.
Nothing crashes. FastAPI's own schema check catches it automatically, before any of the developer's own code even runs, and replies with a standard "your data isn't shaped right" error.
201 specifically means "a brand new thing was successfully created." 200 is a generic "it worked." 201 is more precise, and tells anyone calling this API that a new order now exists.
Every stored order disappears — memory is wiped clean on restart. A real system would use a proper database instead, the same fix explored back in Module 5.
No. Because this service only exposes and uses a defined API, a completely separate Payments service can be built, deployed, and scaled on its own — without this file changing at all.
An API is a contract — a defined way for programs to talk to each other.
A microservice is one small, independent piece of a bigger system.
FastAPI and its schemas give you free structural checks — the business rules are still yours to write.
Even small bugs, like a decimal rounding down instead of properly rounding, can quietly cost real money — which is why tests exist.
The core logic never really changes across this course. Only how it's exposed to the world does.
That's the whole story of Module 12 — take something that already runs correctly, and give it a door the rest of the world can knock on. Notes by Howard · Hands-On Enterprise Python