Faucet v0.1.6 is now available. The headline feature: schema contract locking — a production-grade system that prevents database schema changes from silently breaking your API consumers. Download it now from GitHub Releases, Homebrew, or Docker Hub.
The Problem
Auto-generated APIs have a well-known Achilles’ heel: the schema IS the API contract. When someone runs ALTER TABLE — renames a column, changes a type, drops a constraint — every downstream consumer silently breaks. No deprecation notice. No versioning. No heads-up. They find out in production.
This isn’t theoretical. We’ve seen it happen repeatedly at scale with DreamFactory deployments, and the community has been vocal about it. One recent Reddit thread captured it perfectly:
“Any schema change silently becomes an API breaking change. Add a column? Fine. Rename one, change a type, drop a nullable constraint? Every downstream consumer just broke, and nobody got a heads up.”
Faucet v0.1.6 solves this.
Schema Contract Locking
When Faucet connects to your database, it now takes a contract snapshot — a frozen representation of the schema that your API serves. Schema changes in the database no longer automatically ripple through to the API. You control when and how the API contract evolves.
Three Lock Modes
Configure per database service in faucet.yaml:
services:
- name: mydb
dsn: postgres://localhost/mydb
schema_lock: auto # default
| Mode | Behavior | When to use |
|---|---|---|
none | Live schema = live API. Classic behavior. | Development, prototyping |
auto | Additive changes auto-promote. Breaking changes blocked. | Production (default) |
strict | All changes require explicit promotion. | Regulated environments |
How Auto Mode Works
-
First connect — Faucet introspects the schema and saves a contract snapshot. The API serves this shape. You notice nothing — it’s instant and transparent.
-
Schema drifts — On the next introspection cycle, Faucet compares the live schema against the contract.
-
Additive changes (new column, new table) — Auto-promoted into the contract. New fields appear in API responses. Existing consumers are unaffected — they ignore unknown fields.
-
Breaking changes (rename, type change, drop, constraint tightening) — Blocked. The API continues serving the locked contract. Faucet flags the drift in the admin UI and CLI.
-
You promote explicitly — When you’re ready, run
faucet db promoteor click the button in the UI. The contract updates to reflect the current schema.
Drift Detection in the Admin UI
The Schema Explorer now shows real-time drift status:
- Green — Schema matches the locked contract. No action needed.
- Yellow — Additive changes detected and auto-promoted.
- Red — Breaking changes detected and blocked. Review and promote when ready.
The drift detail panel shows exactly what changed — column renames, type changes, dropped fields — so you know what will break before you promote.
CLI Commands
# Lock the current schema as the API contract
faucet db lock mydb
# Check for drift between live schema and locked contract
faucet db diff mydb
# See what's locked
faucet db status mydb
# Promote: update the contract to match the current schema
faucet db promote mydb
# Remove the lock entirely
faucet db unlock mydb
The faucet db diff output classifies every change as additive or breaking, so you can pipe it into CI or review it before promoting.
OpenAPI Spec Stability
When schema locking is active, the generated OpenAPI spec reflects the locked contract, not the live schema. This means your spec won’t shift underneath tools, SDKs, and code generators that depend on it. Breaking changes show up when you promote — not when someone runs a migration.
Why This Matters
The typical advice for this problem is “add OpenAPI diffing to your CI pipeline.” That’s useful but incomplete — it assumes schema changes flow through PRs. In reality, someone runs ALTER TABLE directly in production, or a migration runs during a deploy, and downstream services discover the breakage at runtime.
Schema contract locking catches both cases. It works whether your schema changes come through CI or through a DBA’s terminal. The API contract holds until you explicitly say otherwise.
Also in This Release
- CONTRIBUTING.md — Faucet is open for contributions. The guide covers development setup, testing, PR expectations, and the project’s coding standards.
- README improvements — Updated documentation and Docker links for better discoverability.
Install or Upgrade
Homebrew:
brew update && brew upgrade faucet
Docker:
docker pull faucetdb/faucet:0.1.6
Go install:
go install github.com/faucetdb/[email protected]
Binary download:
Grab the binary for your platform from GitHub Releases. Available for Linux (amd64, arm64), macOS (Apple Silicon, Intel), and Windows.
What’s Next
Schema contract locking is the foundation for a broader API lifecycle story. Coming in future releases:
- Schema diff in CI — a
faucet openapi diffcommand that outputs oasdiff-compatible breaking change reports for your pipeline - Webhook notifications — get alerted on drift events via webhook
- Migration-aware promotion — tie promotions to your migration tool so contracts advance with your deploy
Star the project on GitHub to follow along, and open an issue if you run into anything.
FAQ
How do I upgrade from v0.1.5?
Run brew upgrade faucet or docker pull faucetdb/faucet:0.1.6. Binary users can download the new release from GitHub. Faucet will automatically run the necessary config database migrations on first startup.
Does locking change anything for existing installations?
New installations default to auto lock mode. Existing installations will have their schema locked on the next introspection cycle. If you prefer the old behavior (live schema = live API), set schema_lock: none in your config.
What databases support schema locking?
All of them. Schema contract locking works across PostgreSQL, MySQL, MariaDB, SQL Server, Oracle, SQLite, and Snowflake.
Can I lock some tables but not others?
Not yet — locking is per-service (per database connection). Table-level granularity is on the roadmap.
Does this add performance overhead?
Negligible. The contract snapshot is stored in Faucet’s SQLite config database and compared during periodic introspection cycles, not on every API request. The API serving path is unchanged.