The LangGraph engine was adopted to get crash recovery and time-travel debugging. A full read of both pipelines, every node and every phase, found neither engine has either one.
This page is what the code actually does, what LangGraph actually buys, and the four phases we would run.
All three sit on the default engine. LangGraph is switched off and defaults to off, so none of this is a LangGraph problem.
The build loop waits on a human by polling the database once a second. If the process dies while it is waiting, the row stays awaiting_approval and nothing is left polling it.
Approving later writes the flag into a row no one is watching. The build never moves. The stale-build repair cannot rescue it either, because that repair deliberately skips awaiting_approval. The user sees a progress bar that never advances.
Build events go into an in-memory queue. The server runs two workers, so a stream request can land on the worker that is not running the build.
When that happens the client attaches to an empty queue and receives nothing but keepalives until it times out. A redeploy does the same thing to every connected stream.
The build loop always starts at phase zero. Completed phase text is written to the database after every phase, and nothing ever reads it back.
Today the only recovery is terminal. A build whose process died gets marked failed with “Build process lost — server was restarted.”
Crash recovery was the headline reason to adopt LangGraph. It is not a LangGraph feature. The data needed to resume is already persisted after every phase — the position in the sequence and the text of everything completed. The resume point is roughly thirty lines of reading it back, and that is true of either engine.
It reuses the prompts and two parsers. It reimplements almost nothing else. The graph itself has eight nodes, two conditionals, and both conditionals mean “stop” — there are no loops. It is a straight line wearing a graph’s clothes.
| Capability | Default engine | LangGraph engine |
|---|---|---|
| Prompt caching | present | missing |
| Fitness approval gate | pauses on fail | skips the gate |
| Deploy gates | present | missing |
| Dev-spec output type | present | missing |
| Gap verdict cross-check | present | missing |
| Pattern matching | present | missing |
| Organization context | present | missing |
| Cancel mid-build | present | missing |
| Phase state saved per phase | after each phase | only at the end |
| Approval writes to the database | present | never does |
| Tests that can fail | core paths | none execute |
Twenty-four tests exist for the LangGraph engine. Every one that executes a node stubs out the model call, so the line that raises on a missing credential is never reached. All twenty-four pass against an engine that cannot complete a single phase. A test suite that cannot fail is worse than no test suite, because it reads as coverage.
Split the pitch into its parts. They have different answers.
Survive a restart and continue. Presented as the framework’s gift. It is not.
The state is already persisted. Reading it back is about thirty lines, and it is the same thirty lines whether the orchestrator is a loop or a graph.
Replay from any historical checkpoint, change an input, run forward. Writing that yourself means versioning every phase output and building a replay path.
The honest question is whether you would use it. For a ten-minute build, “re-run from phase three with a better prompt” is also what the rebuild button does badly.
Typed state, branching edges, loops, parallel fan-out with partial-failure handling. This is where the framework earns its keep.
The build pipeline has seven phases in a straight line and two conditionals that both mean stop. A loop is the correct tool for a straight line.
The governance archetype is the one place a graph is right. Its meeting monitor runs for the life of a project: it ingests transcripts, extracts proposed changes, routes each one through a human, applies what is approved, and loops. That is a long-running, resumable process with human gates in the middle of it — the exact shape the current pipeline cannot express. The strongest argument for keeping the engine is a plan that already assumes it and never says so.
Four phases. The first one does not touch LangGraph at all.
Three small changes to the engine that is actually running in production.
Right now there is nothing to compare, because one engine cannot run.
Does the graph complete builds at comparable cost, and does a durable checkpoint deliver something the thirty lines do not?
If yes, close the gap in phase three. If no, delete the engine, the toggle, and its migration — and correct the published pages that promise a capability neither engine had.
Eleven capabilities, ordered by blast radius. Caching first, because without it the graph costs roughly a third more in input tokens than the engine it is replacing.
Scoring, the phase prompts, the interface contract, the database enums, or the route surface. The first three phases are small, independently revertible changes to paths that already work.