Yes. PostgreSQL's VALID UNTIL clause sets a date and time after which a role's password is no longer valid. If you omit it, the password is valid for all time. It suits temporary access for contractors or break glass accounts, but service accounts need automated rotation first or they will fail on the expiry date.
What the docs say
The CREATE ROLE reference says the VALID UNTIL clause sets a date and time after which the role's password is no longer valid, and that if the clause is omitted the password will be valid for all time. The ALTER ROLE page shows examples: setting a specific expiry with a timestamp, making a password valid forever with the value infinity, and removing a password entirely with PASSWORD NULL.
ALTER ROLE contractor_amy VALID UNTIL '2026-12-31 23:59:59+00';
ALTER ROLE svc_reports VALID UNTIL 'infinity';
ALTER ROLE old_service PASSWORD NULL;
Where it fits
| Role type | Good use of VALID UNTIL | Watch out for |
|---|---|---|
| Contractor or temporary human | Yes, set an end date at onboarding | Remember to extend if the work continues |
| Break glass account | Short expiry, renewed after each test | Test before the real emergency |
| Application service account | Only with automated rotation | A forgotten expiry causes an outage |
| Read only analyst | Yes, with periodic review | Shared credentials defeat the purpose |
The documented behavior is about the password. If a role authenticates by another method, think about what controls its end date there. For example, certificates have their own expiry, and cloud identity tokens are short lived by design. See IAM tokens instead of a database password.
The outage risk
An expiring password on a service account is a scheduled failure unless something changes it first. The login stops working at the stated time, and the first sign is connection errors in production. If you use expiry on service accounts:
- Automate the change of the password and the update of the stored secret together.
- Alert well before the expiry date, with a date you can see in a query rather than in someone's memory.
- Test the rotation path in staging with the same pool and driver settings.
- Remember that existing connections are not necessarily dropped at expiry, while new ones fail. Check how your pool reconnects.
Point 4 is a behavior to test, not assume, because it depends on your setup.
An access review that uses it
- List roles that can log in.
- For each, record the owner, purpose and whether the password has an end date.
- For human and contractor accounts, add an expiry that matches the contract.
- For service accounts, decide between automated rotation and a short lived token approach.
- Remove roles that nobody can name an owner for. The OWASP guidance says to remove accounts when an application is decommissioned and to review accounts regularly.
- Re-run the review on a calendar. See what OWASP says about securing a backend database.
Pair it with least privilege
An expiry limits how long a credential lives. Privileges limit what it can do while alive. Use both. See PostgreSQL predefined roles and least privilege and statement timeouts and connection limits per role.
Safeguard scans dependencies, including database drivers, and can find exposed credentials in repositories. A free scan is at gold.safeguard.sh/scan.
Quick check
What happens if I omit VALID UNTIL?
The CREATE ROLE docs say the password will be valid for all time.
How do I remove a password?
ALTER ROLE with PASSWORD NULL, as shown in the ALTER ROLE examples.
Should service accounts expire?
Only with automated rotation in place, or the expiry becomes a scheduled outage.
Sources
Last reviewed: 19 October 2026.