- Learn
- PostgreSQL
- PostgreSQL CREATE USER
PostgreSQL CREATE USER
Create PostgreSQL users with the right privileges and access controls.
Basic syntax
CREATE USER creates a new role that can log in. The WITH keyword is optional, and so is the password (though you should always set one for application accounts).
CREATE USER vs CREATE ROLE
These two commands are nearly identical. The only difference is the default for the LOGIN attribute.
| Command | LOGIN by default |
|---------|-----------------|
| CREATE USER | Yes |
| CREATE ROLE | No |
These two statements produce the same result:
In practice, use CREATE USER when you want a login-capable account. Use CREATE ROLE when creating a group role that will be granted to other users.
Creating a user with a password
PostgreSQL stores a hashed version of the password. To set a password expiry:
After the expiry date, the user can no longer log in until you update the password.
Granting database access
Creating a user is not enough on its own. You also need to grant access at three levels: the database, the schema, and the tables.
Here is the full sequence for setting up a minimal application user:
Skip any of these and the user will hit a permission error at that level.
Common privilege patterns
Read-only user
Read-write user
Superuser
Avoid superuser accounts for application connections. A superuser bypasses all permission checks, which means a compromised connection can read or destroy anything on the server. Reserve superuser access for database administrators.
Granting privileges on future tables
The GRANT ... ON ALL TABLES command only covers tables that exist at the time you run it. New tables created afterward will not inherit those permissions.
To fix this, use ALTER DEFAULT PRIVILEGES:
This tells PostgreSQL to apply those grants automatically whenever a new table or sequence is created in the public schema. Run it as the role that will be creating tables (usually the database owner or a migration user).
Viewing users
In psql, use \du to list all roles:
\du
Output:
List of roles
Role name | Attributes
-----------+-----------------------------------------------
alice |
appuser |
postgres | Superuser, Create role, Create DB, Replication
reporter |
Use \du+ for additional detail including member roles and comments.
To query users from SQL, use pg_roles:
To see only login-capable users:
Changing a password
To remove the password expiry on an existing user:
Revoking privileges
To remove specific privileges:
To remove all privileges at once:
Dropping a user
PostgreSQL will refuse to drop a user who still owns objects or has privileges. To handle this, use DROP OWNED BY first:
DROP OWNED BY also revokes all privileges granted to the user, so you do not need to run REVOKE separately.
If the user owns objects in multiple databases, you need to run DROP OWNED BY while connected to each database where they have objects.
The createuser shell command
PostgreSQL ships with createuser, a shell wrapper around CREATE USER. It lets you create users without opening psql:
The --pwprompt flag prompts for a password interactively. Common options:
createuser accepts the same connection flags as psql.
Quick reference
| Command | Description |
|---------|-------------|
| CREATE USER name WITH PASSWORD 'pw' | Create a login-capable user |
| CREATE ROLE name WITH LOGIN PASSWORD 'pw' | Same as CREATE USER |
| GRANT CONNECT ON DATABASE db TO user | Allow connecting to a database |
| GRANT USAGE ON SCHEMA s TO user | Allow seeing objects in a schema |
| GRANT SELECT ON ALL TABLES IN SCHEMA s TO user | Read-only table access |
| GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA s TO user | Read-write table access |
| ALTER DEFAULT PRIVILEGES IN SCHEMA s GRANT ... TO user | Apply grants to future tables |
| ALTER USER name WITH PASSWORD 'pw' | Change a password |
| REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA s FROM user | Remove table privileges |
| DROP OWNED BY user | Remove all owned objects and privileges |
| DROP USER name | Delete the user |
| \du | List all roles in psql |
| SELECT * FROM pg_roles | Query all roles from SQL |
| createuser name | Create a user from the shell |