Read the story

Architecture

Prices quotes from each office's price book.Saved lines keep their price.

Coordinators build options in a workspace, and the pricing engine prices every line from the office's published price book. The save writes the price, tier, label and book version onto each line, and the PDF, the Excel and every total read those back.

14.5 hours

from the first commit to v1.0.0

4 fields

frozen on every saved line: price, tier, label and price book version

5 min

from a 4:58 AM fix for a coordinator's ask to shipping it as v1.14.0

3 offices

each with its own versioned price book; only an admin can publish a change

New York --:-- simulated

A coordinator saves an option
Hybridge Treatment Estimator Coordinators build options in a workspace, and the pricing engine prices every line from the office's published price book. The save writes the price, tier, label and book version onto each line, and the PDF, the Excel and every total read those back. Google sign in Auth.js v5, DB sessions CDF registry API the day's consults GitHub Actions deploy on a v tag WIF Coordinators 3 offices, 2 domains Estimate workspace drag, phases, scenarios estimator-prod Cloud Run, Next.js 16 Postgres 16 Cloud SQL, frozen prices PDF and Excel office logo, workup first Sequence engine vendored, no registry Pricing engine 5 models, one resolver build save option frozen price as saved sign in consults migrate + fees visit plan price lines GCP hybridge-estimator, us-east1

Hover a part to trace what it touches. Click it for its notes.

  • Built by me
  • Managed by Google
  • Outside system
  • Main data path
  • On demand
  • Credentials cross

When it breaks

What each failure does, and what it does not do.

  1. A release goes bad

    Traffic moves back to the previous revision in about ten seconds. The prior revision stays warm for exactly this.

    docs/runbook/incidents.md:40

  2. The CDF is slow or unset

    After 8 seconds the coordinator gets their screen back with an empty day and a reason. Production never fills it with sample names.

    lib/schedule/registry.ts:83

  3. The database zone fails

    Restore to a new instance from point in time recovery, point the secret at it, redeploy. The runbook's target is 5 to 10 minutes.

    docs/runbook/incidents.md:286

What I tuned

Small choices that keep it fast and cheap.

  1. Code for flow, rows for prices

    The decision tree is TypeScript with tests. Each office's prices are versioned rows with their own approval, so an office can change a price without a deploy.

    docs/architecture/0001-stack-decisions.md:182

  2. Scale to zero

    Cloud Run runs zero to five instances and bills per request. October 1 to 28 cost 14 cents of Cloud Run.

    .github/workflows/deploy-prod.yaml:141

  3. The arch follows the options

    Nobody picks Upper, Lower or Both anymore. The arch is set from the options inside every save and delete transaction.

    lib/summary/archSync.ts

Guards

Rules the code enforces, not rules people remember.

  1. Prices frozen on each line

    Four columns on every saved line: price, tier, label and price book version. Totals, PDF and Excel read those back, never the live book.

    lib/db/schema/estimate.ts:138

  2. Reopen moves, never copies

    Reopening moves the live rows to the next revision, so payments still point at the right lines. The update is guarded on status and revision, so two clicks cannot both move them.

    app/_actions/estimate.ts:672

  3. No grant means read only

    A new account lands as a viewer and can write nothing until someone grants a role. It fails closed.

    lib/auth/guards.ts:29

What it costs

Measured from the Google Cloud billing export, October 1 to 28, net of credits. The always on database is almost all of it, $23.45 of that for the instance alone. The app itself scales to zero between consults.

$34in October

  • $33.20 Cloud SQL, always on
  • $0.39 Secret Manager
  • $0.15 Image registry
  • $0.14 Cloud Run, per request