From bf7f829d02179a897ac71805093ad64fab498546 Mon Sep 17 00:00:00 2001 From: rob thijssen Date: Sun, 3 May 2026 19:28:32 +0300 Subject: [PATCH] fix(api): don't run migrations as moments_ro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The api connects as the read-only role and was failing on startup with `permission denied for schema public` because moments_ro lacks CREATE rights — moments_rw owns the database and runs migrations. Migrations are now owned exclusively by moments-worker. In deploy (step 7) systemd ordering ensures the worker runs at least once before the api unit starts, so the schema is in place by the time the api accepts traffic. Co-Authored-By: Claude Opus 4.7 (1M context) --- crates/moments-api/src/main.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/moments-api/src/main.rs b/crates/moments-api/src/main.rs index 4ce2685..6f27ec8 100644 --- a/crates/moments-api/src/main.rs +++ b/crates/moments-api/src/main.rs @@ -36,8 +36,12 @@ async fn main() -> anyhow::Result<()> { init_tracing(); let args = Args::parse(); + // The api connects as moments_ro and never writes — migrations are owned + // by moments-worker, which is the database owner (moments_rw). Running + // migrations from here would fail with `permission denied for schema + // public`. The worker must have run at least once before the api accepts + // traffic; in deploy this is ordered via systemd dependencies (§3). let store = PgStore::connect(&args.database_url).await?; - store.migrate().await?; let state = AppState { store: Arc::new(store), };