DbUp runs your migrations. It never asks whether they should run.
A lot of .NET teams start with DbUp, and it is easy to see why. Add a NuGet package, drop your .sql files in a folder, mark them as embedded resources, and a few lines of C# apply every pending script at deploy time. No server, no daemon. For one service owned by the people who write it, that is often enough.
It stops being enough for the same reason every time. The database DbUp deploys to is the same database a developer opens a client against on a Friday to "just fix one row." DbUp has nothing to say about that, because it was never meant to. It runs scripts. Governing a database is three problems, and running scripts is a slice of one of them.
What DbUp does well
DbUp is minimal in the good sense. MIT licensed, small, one job: apply the scripts that have not run, record them in a journal table, stop. It reaches past SQL Server too, with providers for PostgreSQL, MySQL, SQLite, and Oracle. Ship a .NET app and DbUp folds into the build artifact so cleanly that migrations stop being a separate step.
It is honest about its model. DbUp is forward-only on purpose. The maintainers do not do down scripts, and their reasoning holds: a rollback script is code you wrote before you knew how the failure would look, and it fails you exactly when you are panicking. I agree with that more than I disagree.
So this is not a bad tool. It is a good migration runner. A runner covers the machine-to-database path and only that.
Governance is three problems, not one
Bytebase is not a bigger migration tool. It is a database governance platform, and governance is change, access, and compliance held in one system:
- Change. Who can alter what, reviewed against 200+ SQL rules, approved by the right person, applied with history and diff you can read later.
- Access. Who can query production, through a governed SQL Editor, with sensitive columns masked on read and temporary access that expires on its own.
- Compliance. One audit log across both of the above, so change and access answer to the same policy and the same record.
DbUp sits inside the first bullet, under "applied." To reproduce the rest you bolt together DbUp plus a ticketing tool to collaborate on the change, plus a review step wedged into CI, plus a separate access or masking tool, plus a hand-rolled audit export. Five things that do not share state. The cost is not missing features. It is the seams between them, and the seams are where changes slip through unreviewed and access outlives the person.
Where the two differ
| DbUp | Bytebase | |
|---|---|---|
| What it is | A .NET migration library | A unified database governance platform |
| How you drive it | C#/.NET code plus embedded SQL scripts | Web GUI, API, GitOps, Terraform provider |
| How it runs | Compiled into your app (needs .NET runtime) | Standalone service: single Go binary, Docker, or Kubernetes |
| Databases | SQL Server, PostgreSQL, MySQL, SQLite, Oracle | MySQL, PostgreSQL, SQL Server, Oracle, and twenty-plus more |
| Change | Applies forward-only scripts, journal table | Reviewed, approved, issue-based change with history and diff |
| Access | None | Governed SQL Editor, masking on the query path, just-in-time access |
| Compliance | Journal table only | One audit log across change and access |
| License | MIT | MIT, with Enterprise features under a commercial license |
The path DbUp was never built for
Every serious database incident I have watched lives on the human-to-database path, not the deploy path.
A developer points a client at prod instead of staging and runs a DELETE with no WHERE. Someone adds a non-nullable column to a 200-million-row table and locks it at peak. A contractor still reads a table full of SSNs three months after the engagement ended. None of these touch your deploy pipeline. DbUp cannot see any of them, because it only runs the scripts you compiled into it, only when your app runs.
Three people stand around that database. The developer wants the change out today. The DBA wants to prevent the outage. The security engineer wants to prevent the breach. DbUp serves the first one halfway and the other two not at all. That is not a knock on DbUp. It is the boundary of what a runner is.
Govern the dangerous path first
You do not throw DbUp away on day one. Your deploy pipeline is not what is hurting you. The ad-hoc UPDATE on prod is.
Put Bytebase in front of the human-to-database path first: a governed SQL Editor with masking, production changes routed through review and approval, one audit log underneath. DbUp keeps deploying while you do it. Most teams then move the scheduled migrations in too, because once review, access, and audit live in one place, running deploys from somewhere else feels like keeping two sets of books.
A migration runner keeps your schema moving. Governance decides where it is allowed to go. If you have outgrown the first and started worrying about the second, that is the line DbUp does not cross. See how Bytebase handles database change and access control.