IL-0315 Railway · 2025-10-28database
Railway's backend API went down when an index build locked a billion-row Postgres table and used up every connection
Railway's Dashboard, CLI and Public API depend on a backend that uses Postgres as its primary datastore. A routine change added a new column with an index to a table of about 1 billion records that nearly all API operations use. The index was created without Postgres' CONCURRENTLY option, so it took an exclusive lock on the whole table, and every query queued behind it. The API servers kept accepting requests and each new database connection blocked, and Railway's PgBouncer configuration allowed more connections than the Postgres limit, so all connection slots, including the administrative ones, were exhausted.
Engineers could not open an administrative connection to stop the index creation. While other recovery options were being explored, the migration finished on its own after about 30 minutes and released the table lock, the queued operations ran and the connection pools returned to normal. The root cause was identified at 18:56 UTC, gradual recovery was confirmed at 19:00 and full service at 19:15. Running deployments and platform-level features stayed online throughout.
- Severity
- –
- Scope
- Dashboard inaccessible, CLI operations that use the API failed, GitHub-based deployments delayed and all Public API operations disrupted; running deployments and platform-level features stayed online
- Users affected
- Users who opened the dashboard, used the CLI or started a GitHub-based deploy during the incident
- Region
- –
- Time to detect
- 2m
- Time to resolve
- 41m
Symptoms
At 18:36 UTC on 28 October 2025, two minutes after a database change went live in production, Railway's internal monitoring alerted and paged the engineering team. The dashboard could not be opened, CLI operations that use the API, such as railway up, failed, GitHub-based deployments were delayed because webhook processing failed, and all Railway Public API operations were disrupted.
The change added a new column with an index to a table of about 1 billion records that nearly all API operations use. All queries against the database queued behind the index operation, and the API servers kept accepting requests whose database connections blocked on the locked table straight away. The connections that PgBouncer opened went past the Postgres connection limit and took every connection slot, the administrative ones included.
When engineers tried to connect and stop the index creation, Postgres refused with "FATAL: remaining connection slots are reserved for roles with privileges of the "pg_use_reserved_connections" role". Without an administrative connection, no command could be run to terminate the operation.
Symptom Service outageLock contention or deadlockDatabase overload
Root cause
Root cause Faulty deployment
- Trigger
- A routine schema change to the backend's Postgres database, introduced at 18:23 UTC and live in production at 18:34 UTC, that added a new column with an index without the CONCURRENTLY option.
Detection
Internal monitoring alerts paged the engineering team at 18:36 UTC, and the incident was declared at 18:41 UTC.
Remediation
- The index migration finished after about 30 minutes and released the table lock, and the queued operations and connection pools recovered
Action items
- Enforce CONCURRENTLY for all index creation in CI and block pull requests that do not use it
- Adjust PgBouncer pool limits so they cannot overwhelm the Postgres instance's capacity
- Configure database user connection limits so administrative access stays possible during incidents
Lessons
–
Sources
Related cases
IL-0369Railway's backend API went down when a column migration waited on locks and replicas could not get database connectionsRailway · 2025same root cause · shared Database, Database proxy and connection pooler
IL-0307Supabase's Postgres connection pooler Supavisor 2.0 dropped connections for about 80% of us-east-1 tenantsSupabase · 2025same root cause · shared Database, Database proxy and connection pooler
IL-0356Every domain hosted on Railway returned HTTP 404 to new connections for five minutes because route lookups failedRailway · 2026same root cause · shared Database
IL-0136A deployment that cleared an internal service's caches at peak traffic sent 20 times the normal load to the Azure OpenAI metadata backend in Sweden Central, and health checks that depended on its database restarted instances in a loop for almost six hoursMicrosoft Azure · 2026same root cause · shared Database
IL-0570Dropping an unused MySQL table stalled queries on its busy parent table and crowdworks.jp was hard to reach for a minuteCrowdWorks · 2026same root cause · shared Database
IL-0510MIT Learn's RDS PostgreSQL ran out of storage after a release and learn.mit.edu returned 503s and 504s for hoursMIT Open Learning · 2026same root cause · shared Database
IL-0380A compaction change in InfluxDB Cloud us-east-1 dropped data from compacted files, and queries missed data for weeksInfluxData · 2026same root cause · shared Database
IL-0547Buildkite annotation queries timed out and drove database CPU up across shards after a migration removed an indexBuildkite · 2025same root cause · shared Database
IL-0327After a blue/green upgrade of CircleCI's workflows database every query hit disk, and workflow starts lagged or failedCircleCI · 2025same root cause · shared Database
IL-0324Three MediaWiki deployments lost Memcached after a PHP 8.1 rollout and overloaded the External Storage database clusterWikimedia Foundation · 2025same root cause · shared Database
IL-0552CircleCI's archival database ran out of storage, slowing workflow and job starts and the display of workflows in the UICircleCI · 2025same root cause · shared Database
IL-0554A database migration used up Sentry US's Postgres connections, and the site and event ingestion were down for 22 minutesSentry · 2024same root cause · shared Database
IL-0571STORES reservation returned bursts of 504 errors when a smart-list query held a database process for over 20 minutesSTORES · 2024same root cause · shared Database
IL-0293Cloud Bigtable in us-central1 had higher latency and connection errors for about 32 hours from low-rate packet lossGoogle Cloud · 2023same root cause · shared Database
IL-0523TANF-app production deployments were blocked for two months when a search-index migration ran out of database disk spaceU.S. Department of Health and Human Services · 2023same root cause · shared Database
IL-0567Aurora MySQL behind Cookie Run: OvenBreak hit 100% CPU after a sales-ranking feature launch, and players could not playDevsisters · 2023same root cause · shared Database
IL-0483Replicate's website and API returned slow responses and HTTP 500s for two hours as PostgreSQL connections ran outReplicate · 2023same root cause · shared Database
IL-0371Half of new connections to Render Postgres databases with point-in-time recovery failed while their backup jobs ranRender · 2023same root cause · shared Database
IL-0524An index migration locked Open Collective's whole Transactions table and degraded the service for nearly an hourOpen Collective · 2023same root cause · shared Database
IL-0328A field type change in the database of CircleCI's job distribution service left all jobs stuck in "not running"CircleCI · 2021same root cause · shared Database
IL-0566Hot ranges after a Cookie Run: Kingdom guild update drove CockroachDB nodes to 100% CPU, forcing emergency maintenanceDevsisters · 2021same root cause · shared Database
IL-0391GoCardless API requests timed out for about 15 seconds while a Postgres migration waited for an AccessExclusive lockGoCardless · 2015same root cause · shared Database
Check your cluster for this
For AI tools and scripts
- This case as JSON: https://incidentlib-api.benchlet.com/cases/IL-0315
- The cases most like it: https://incidentlib-api.benchlet.com/cases/IL-0315/similar
- MCP server (Streamable HTTP, no key):
https://incidentlib-mcp.benchlet.com/mcp
The API needs no key. The MCP server offers search_incidents, get_incident, list_incidents, get_topic and vocab; both are explained on API and MCP.