---
title: "Security Disclosure Recommendation: Rotate PostgreSQL Database Credentials"
description: "Learn how to Security Disclosure Recommendation: Rotate PostgreSQL Database Credentials"
date: 2026-10-22T00:45:42.930Z
authors: ["Mykal Machon"]
category: "Engineering"
url: https://blog.railway.com/p/security-disclosure-recommendation-rotate-postgresql-database-credentials
---

# Security Disclosure Recommendation: Rotate PostgreSQL Database Credentials

> This guide is part of Railway's response [to the security disclosure published on October 21, 2026](https://blog.railway.com/p/security-disclosure-wednesday-october-21st).

*If you run PostgreSQL on Railway, regenerate its password, redeploy every service that uses it, and confirm nothing is still connecting with the old credential.*

If your PostgreSQL password or `DATABASE_URL` may have been exposed, rotate your credentials. The same steps work for scheduled rotation. This guide applies if your database uses the Railway [PostgreSQL template](https://docs.railway.com/databases/postgresql). The fastest path is **Regenerate** in the Database View, which changes the password inside PostgreSQL and updates the service variables in one step.

If you suspect the credential isn't compromised and you need zero downtime, use the dual-role flow in [Rotate credentials without downtime](https://docs.railway.com/guides/rotate-credentials-zero-downtime#rotate-a-database-password) instead. If you suspect a leak, cutting off the old credential matters more than the short outage while your services redeploy. Regenerate first.

## Before you rotate

Three checks tell you how exposed the credential is and what you must update afterwards.

1. Find every consumer. Open the PostgreSQL service's **Variables** tab. Services that use [reference variables](https://docs.railway.com/variables#referencing-another-services-variable) such as `${{ Postgres.DATABASE_URL }}` pick up the new password on their next deploy. Services with a pasted connection string don't, so note them.
2. Check public access. Open the PostgreSQL service's **Settings** and find **Networking**. If **Public Access** is enabled, the credential is usable from anywhere on the internet through the [TCP proxy](https://docs.railway.com/networking/tcp-proxy) until you rotate. Remove public access now if nothing outside the project needs it. A private database is only reachable over the project's [private network](https://docs.railway.com/networking/private-networking).
3. List external consumers. Anything that uses `DATABASE_PUBLIC_URL` (local development, CI, BI tools, cron jobs on other hosts) needs the new value pasted in by hand.

## Regenerate the password

Regenerate is the supported way to change a database password on Railway. It keeps the database and the variables in sync.

1. Open the PostgreSQL service and click the **Database** tab, then **Config**.
2. In the **Connection** section, click **Regenerate** next to the password. Railway changes the password inside PostgreSQL and updates `POSTGRES_PASSWORD`. In the template, `PGPASSWORD`, `DATABASE_URL`, and `DATABASE_PUBLIC_URL` reference it, so they change too. See [Database View: Connection](https://docs.railway.com/databases/database-view#connection).
3. Railway restarts the database to apply the new password, so every open session drops, including any an attacker had open. Your services can't reconnect until you redeploy them in the next section. During an incident, that is the goal.

> ⚠️ Don't edit `POSTGRES_PASSWORD` or `PGPASSWORD` by hand, and don't run `ALTER USER` yourself. Each changes only one side and leaves the variable and the database out of sync. If that already happened, see [how to recover](https://docs.railway.com/databases/database-view#connection).

## Redeploy the services that use it

Containers read variables only at startup, so every service that uses the credential must be redeployed.

1. Redeploy every service that references the PostgreSQL variables. Regenerate redeploys only the database, so these services keep the old password until you do.
2. If a service has a pasted connection string, replace it with the reference `${{ Postgres.DATABASE_URL }}` so the next rotation reaches it automatically, then deploy.
3. Optional: redeploy one service from the CLI with [`railway redeploy`](https://docs.railway.com/cli/redeploy).
   ```Shell
   railway redeploy --service backend

   ```
4. Update external consumers with the new `DATABASE_PUBLIC_URL`.

A [healthcheck](https://docs.railway.com/deployments/healthchecks) that exercises the database fails a deploy that has the wrong credential, so you catch a bad value before it takes traffic. It won't flag a service you forgot to redeploy, because Railway only runs healthchecks at deploy time.

## Verify the rotation

Confirm the new credential works and nothing is still connected with the old one.

1. Check each dependent service's deploy logs for a successful connection and no `password authentication failed` errors.
2. Open the **Database** tab and confirm the **Data** view loads tables. It uses the same variables.
3. Connect with the new credential using [`railway connect`](https://docs.railway.com/cli/connect).
   ```Shell
   railway connect Postgres

   ```
4. List current sessions. The restart dropped every session from before the rotation, so a session you don't recognize connected with the new password. Find out where it got it.
   ```SQL
   SELECT pid, usename, client_addr, application_name, backend_start, state
   FROM pg_stat_activity
   WHERE datname = current_database();

   ```
5. If you find sessions you don't recognize, terminate them.
   ```SQL
   SELECT pg_terminate_backend(<pid>);

   ```

## Look for misuse

A rotated password stops future access. These checks show whether the old credential was used.

- Railway [audit logs](https://docs.railway.com/enterprise/audit-logs) show who viewed or changed variables on the PostgreSQL service and when. Workspace admins can filter by project and event type. [Retention depends on your plan](https://docs.railway.com/enterprise/audit-logs#audit-log-retention).
- The PostgreSQL service's deploy logs include failed logins. Use the [log filter](https://docs.railway.com/observability/logs) to search for `authentication failed`. PostgreSQL doesn't log successful connections or client addresses by default.
- Inside the database, look for roles you didn't create with `SELECT rolname FROM pg_roles;`, for new extensions, and for unexpected row counts or recently modified rows.
- If data was altered, preserve the evidence first, then restore from a [backup](https://docs.railway.com/volumes/backups) or use [point-in-time recovery](https://docs.railway.com/volumes/point-in-time-recovery).

If you have any other questions, contact Railway support at <support@railway.com>.


---

Open this post in a browser: https://blog.railway.com/p/security-disclosure-recommendation-rotate-postgresql-database-credentials
