Chapter Four · The Anatomy of a Service
The Anatomy of a Service
Stagedoor's codebase is one file of 3,000 lines where routes build SQL strings, read the environment mid-request, and share a database connection opened at import. Five topics give the service a shape: three layers with one rule about imports, dependencies built once at startup and passed down, a request context that travels without being passed by hand, ordered rings of middleware around the handler, and configuration read once, typed, before the first request.
Marek inherited handlers.py. Thirty-one route functions in 3,000 lines, each one parsing its own body, building its own SQL string, raising HTTPException from inside loops over seats, and reading os.environ whenever it needed a value. Line 12 opened the database connection at import time, and every test that imported anything connected to a database. The hold rule lived in four routes with four slightly different opinions about how long a hold lasts. When the worker needed to expire holds, it got a fifth copy, because the other four could not run without a request to raise into.
This chapter restructures that file into the shape every later chapter's code quotes. Transport, domain and storage become three packages with one rule about which may import which, and a linter that holds the rule. A single build_service function constructs the pool, the clients and the clock once, from a typed config, and hands them to handlers that construct nothing. The five facts that belong to a request and to no function, who is calling, which request this is, how much time is left, which trace and which tenant, ride in a frozen context carried by the async task and rebuilt on the far side of every queue. Six rings of middleware wrap the handler in an order chosen so that the cheap refusals run before the 100-millisecond hash and the logger sees every outcome. And configuration is parsed once, at startup, so a missing key stops the process before it binds the port instead of forty minutes later, as a 500.
None of the three wounds from Chapter 1 closes here. Seat 14C, the double charge and the late emails are all fixed in Chapters 6 through 8, and each fix is a change to one storage function, one domain rule or one worker, in a codebase that has the layers to make that a 40-line diff. Chapter 5 puts the login handler into the transport layer this chapter built, and the boundary that Chapter 3 drew now has an inside.