Here's a comprehensive Markdown guide you can save as postgres-application-user-setup.md.
This guide explains how to securely configure PostgreSQL for production applications.
Instead of connecting your application using the postgres superuser, you'll create:
- A dedicated application user
- A database owned by an administrative user (
postgres) - Proper permissions for the application user
- Protection against accidental database deletion
This is the recommended setup for production environments.
The default postgres user is a Superuser.
A superuser can:
- Create and delete databases
- Create and delete users
- Change server configuration
- Bypass all permissions
- Read or modify any database
- Execute dangerous administrative commands
If your application credentials are ever leaked, an attacker gains complete control over your PostgreSQL server.
Instead, applications should always connect using a dedicated user with the minimum permissions required.
PostgreSQL Server
│
┌───────────────┴───────────────┐
│ │
postgres (Admin) app_user
Superuser Application User
│ │
│ │
└────── manages database ───────┘
│
my_database
Only the administrator manages databases.
The application only works with data.
Login as the PostgreSQL superuser.
CREATE ROLE app_user
WITH
LOGIN
PASSWORD 'StrongPassword123!'
NOSUPERUSER
NOCREATEDB
NOCREATEROLE
NOREPLICATION
INHERIT;| Option | Meaning |
|---|---|
| LOGIN | Allows the user to log in |
| PASSWORD | User password |
| NOSUPERUSER | Cannot bypass permissions |
| NOCREATEDB | Cannot create databases |
| NOCREATEROLE | Cannot create users |
| NOREPLICATION | Cannot perform replication |
| INHERIT | Inherits granted permissions |
Always create databases using the administrator.
CREATE DATABASE my_database;Verify:
SELECT datname
FROM pg_database;GRANT CONNECT ON DATABASE my_database TO app_user;\c my_database
By default, objects are created in the public schema.
Grant the application access.
GRANT USAGE ON SCHEMA public TO app_user;
GRANT CREATE ON SCHEMA public TO app_user;This allows:
- Creating tables
- Creating indexes
- Creating views
- Creating sequences
- Creating functions
If the database already contains tables:
GRANT ALL PRIVILEGES
ON ALL TABLES
IN SCHEMA public
TO app_user;
GRANT ALL PRIVILEGES
ON ALL SEQUENCES
IN SCHEMA public
TO app_user;
GRANT ALL PRIVILEGES
ON ALL FUNCTIONS
IN SCHEMA public
TO app_user;New tables created later should automatically be accessible.
ALTER DEFAULT PRIVILEGES
IN SCHEMA public
GRANT ALL PRIVILEGES
ON TABLES
TO app_user;
ALTER DEFAULT PRIVILEGES
IN SCHEMA public
GRANT ALL PRIVILEGES
ON SEQUENCES
TO app_user;
ALTER DEFAULT PRIVILEGES
IN SCHEMA public
GRANT ALL PRIVILEGES
ON FUNCTIONS
TO app_user;Check the role.
SELECT
rolname,
rolsuper,
rolcreatedb,
rolcreaterole,
rolreplication
FROM pg_roles
WHERE rolname='app_user';Expected:
rolsuper false
rolcreatedb false
rolcreaterole false
rolreplication false
postgresql://app_user:StrongPassword123!@localhost:5432/my_database
Example:
postgresql://app_user:mypassword@localhost:5432/my_database
The application user can:
- Connect to the database
- Create tables
- Drop tables
- Alter tables
- Create indexes
- Create sequences
- Create views
- Create triggers
- Create functions
- Insert data
- Update data
- Delete data
- Truncate tables
- Run migrations
- Execute stored procedures
Essentially everything inside the database.
The application user cannot:
- Drop databases
- Create databases
- Create users
- Delete users
- Become a superuser
- Change PostgreSQL configuration
- Perform replication
- Manage server-level settings
Suppose your application has an SQL injection vulnerability.
If it uses:
postgres
An attacker could:
DROP DATABASE production;Or:
CREATE ROLE hacker SUPERUSER;Or:
ALTER SYSTEM SET ...Complete server compromise.
With app_user, none of these commands work.
The attacker is limited to the application's own database objects and cannot perform server administration.
Recommendation: No.
Database creation should be done only during:
- Deployment
- Infrastructure provisioning
- DevOps automation
- CI/CD pipelines
Applications should simply connect to an existing database.
Repeat:
CREATE DATABASE another_database;
GRANT CONNECT ON DATABASE another_database TO app_user;Then configure schema permissions inside each database.
✅ Never use the postgres user in applications.
✅ Use a dedicated application user.
✅ Use strong passwords.
✅ Enable SSL connections.
✅ Rotate passwords regularly.
✅ Limit network access using pg_hba.conf or firewalls.
✅ Keep backups.
✅ Separate admin credentials from application credentials.
| Role | Purpose |
|---|---|
| postgres | Database administration |
| app_user | Application access |
The application user has everything needed for normal application operation while being restricted from server administration tasks.
This follows the principle of least privilege and is the recommended setup for production PostgreSQL deployments.
This guide is suitable for committing to your repository as docs/postgres-application-user-setup.md or using as internal infrastructure documentation.