WritingDatabricks (DBRX)Databricks (DBRX)published Sep 9, 2026seen 2h

Introducing Consort: Test-driven development on a branching database

Open original ↗

Captured source

source ↗

Introducing Consort: Test-driven development on a branching database | Databricks Blog Skip to main content

Summary

What changes with database branching

An agentic development workflow with database branching

How to try Consort yourself

For 25 years I built software on the practices I grew up with: Kent Beck’s TDD, Martin Fowler’s Refactoring, Uncle Bob’s Clean Code, Jez Humble and Dave Farley’s Continuous Delivery, Pramod Sadalage and Scott Ambler’s Evolutionary Database Design. With modern software development practices, code can be branched, environments are containerized and infrastructure becomes code. But one part of the stack never played along: the database. It sat there as a rigid monolith, and we accepted many workarounds because of it such as mocks instead of the real thing, a shared staging box and schema changes running as a careful ceremony. I’ve been speaking with software dev teams about Lakebase Postgres for a while now, and how it changes what we used to do. You might have heard me say: Branch your database like you branch your code. But what does that mean in practice, and how do I apply it? What changes with database branching Integration testing comes home to the inner loop Testing against a real database used to be an outer-loop concern. Standing up a database, seeding it with schema and data, versioning the schema, and doing it per unit test was too expensive, so I didn’t. Nobody did. We wrote unit tests against mock objects instead, not because mocks were good, but because a real database in the inner loop was out of reach. And we know that mocks drift over time; they fall out of step with how the database actually behaves and the more you maintain them, the less real behavior they verify. Copy-on-write branching removes the reason for mocks to exist. You create an isolated branch of the real database in roughly constant time, regardless of data size. The first test I write, TDD-style, runs against a live branch of real data, not a fake. I can run destructive tests, blow up everything, hose up my schema, and never touch what the rest of the team is on. It’s my branch. When I’m done, I throw it away. Code and schema ship as one Because the schema now travels as versioned migrations (Alembic, Flyway, or Knex, by stack), a schema change and the code it depends on, moves together as a single unit. You merge the schema (not the data), and the code lines up with it. Two engineers I showed this to, on different teams, landed on the same phrase for it: Data CD. The 2 a.m. production break gets caught before it happens When something breaks in production, it’s usually at 2 a.m., and you’re reverse-engineering what changed. Branching flips the timing. On every pull request, and again on merge, you create a fresh database branch from the target environment, run the migrations and the full test suite against it and find the regression or the collision before it gets deployed. The schema change is in the pull request as a migration, so your DBA reviews it there as a code owner, not a ticket in a downstream queue. Promoting a schema change used to be a high-risk ceremony. Now you branch prod, apply the change, test it in isolation and promote. Doing the same on a vanilla cloud Postgres setup takes a pile of fragile DevOps scripting and wastes precious human time. None of this is a database feature you switch on. It’s a shift in when the hard testing happens, all the way left, in the loop where you’re actually writing the code. An agentic development framework with database branching Now that the infrastructure for branching is here, what’s been missing from the conversation is something that puts it to work in a real development loop. That’s why I built Consort . Consort is an open-source agentic development framework that uses Lakebase branching as the foundation of its test-driven build. If you know Scrum, the idea is in the name. Each role on the team (product owner, spec author, architect reviewer, DBA, test strategist, and a navigator/driver pair) becomes an agent. They perform together, led by a conductor, and ultimately perform as a consort. Work runs in two lanes: a spec-first design lane where intent is agreed and frozen, and a build lane that runs the full red/green/refactor cycle against a live branch of the real database. A few components make it hold together when an agent is the one writing the code. The agent gets a real edge to hit. Give an agent something concrete and it figures the problem out, because it can tell when the code doesn’t work. Give it a hermetic, mocked test and it will happily hand you something that looks like it passes and falls over the moment you run it against a real database. A live branch of real data is the concrete edge, the agent can’t assume its way around a database that’s actually there. The driver can’t move the goalposts. The role that writes the code cannot change a test to make it pass. The only exception is a genuine supersession, a later story that legitimately retires an old test. Green means the test ran and passed against the real database branch, not because the agent said it did. The conductor is code, not an agent. The role a team calls the scrum master becomes a deterministic state machine. It routes the work, holds the human-approval gates and reroutes to the responsible role when something conflicts, so the process that drives the cycle can’t be argued out of a step or lose its place. It doesn’t lose the mission. The complaint I hear most about other frameworks is after a few days the agent loses the mission, you get frustrated, and you restart. Consort keeps each feature’s artifacts in a dedicated directory structure the agents read from as a contract between roles. It’s the same handoff a real team runs: each specialist reviews the work, adds their concern, and passes it to the next.

As an optimization strategy (so your agents don’t spend the beginning of each turn re-scanning everything), Consort feeds each agent a scoped context package, the exact tests to pass, the design requirements and where those tests live, instead of turning it loose on the whole codebase. Unscoped access is how agents drift, and how they spend eons thrashing over the code trying to figure out what to do and where it goes until they forget what DRY means. The architect reviews the spec before any code is written and layers in the design you care about including the cross functional requirements, the layering, patterns like...

Excerpt shown — open the source for the full document.

Notability

notability 6.0/10

New tool for test-driven database development, notable but niche