A separate migration runner
The problem it solves
Four EF Core contexts share one PostgreSQL database — the application's, Billing's, the identity host's and the gateway's — plus Quartz.NET's tables and Wolverine's outbox. If each service migrated its own schema on start-up, two replicas could race on the same migration, and a service could start against a schema another service had not finished.
Blouppy.MigrationRunner applies every migration, builds the messaging tables, then
exits. Aspire starts it first and starts the API, the identity host and the gateway only
once it has completed. It exits 1 on a failure, so nothing starts against a schema in
an unknown state.
In production it is a deliberate step: the runner refuses to touch a Production database
unless Migrations:AllowInProduction is set.
What it costs
- One more project, which references every context's assembly.
- A step in deployment: the compose file runs it before the services.
What you can relax
Run it standalone, without Aspire, given the connection string:
ConnectionStrings__blouppy-db="Host=…;Database=blouppy;Username=…;Password=…" \ dotnet run --project back/Blouppy.MigrationRunnerSeeding is not its job, and stays with the services that own the data — so you can run the runner against any environment without writing sample rows.