# How to create and manage PostgreSQL users

Create additional PostgreSQL users (called **roles**) with only the access they need - for example a
read-only role for reporting, or a separate role per application. Your application already has a main
role; add extra roles rather than sharing it.

## The TurboStack way: extra database users

The simplest option is to let TurboStack manage the user for you:

1. Open the application's **Configure application** dialog and go to the **Database Info** tab
   ([Applications](../../platform/hosts/applications/index.md)).
2. Add an **extra database user** and choose its role - **read-only** or **admin**.
3. Publish the host. TurboStack creates the role and shows its credentials on the
   [Credentials](../../platform/hosts/credentials.md) tab.

Use this for the common cases; it keeps the role in your configuration and recreates it consistently.

## Create a role by hand (SQL)

For finer-grained grants, connect over [SSH](../../platform/hosts/ssh.md) and run SQL with `psql`.
Grant only what the role needs.

A read-only role on one database:

```sql
CREATE ROLE prod_readonly LOGIN PASSWORD 'a-strong-password';
GRANT CONNECT ON DATABASE prod_db TO prod_readonly;
\c prod_db
GRANT USAGE ON SCHEMA public TO prod_readonly;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO prod_readonly;
-- also cover tables created later:
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO prod_readonly;
```

A role with full access to a single application database:

```sql
CREATE ROLE prod_app LOGIN PASSWORD 'a-strong-password';
GRANT ALL PRIVILEGES ON DATABASE prod_db TO prod_app;
```

> [!TIP]
> Grant on the specific database and schema, not cluster-wide. Do not make application roles
> `SUPERUSER` or give them `CREATEROLE`.

For a role to connect remotely, it also needs a host-based access rule - see `postgresql_extra_access`
in [Configure PostgreSQL](configure.md) and [Connect remotely](connect-remotely.md).

## Rotate a password

```sql
ALTER ROLE prod_readonly PASSWORD 'a-new-strong-password';
```

Update the password wherever the role is configured (the application, or your client) at the same time.

## Verify access

```sql
\du prod_readonly
```

Then connect as that role and confirm it can do what it should - and nothing more.

## Related

- [Configure PostgreSQL](configure.md)
- [Import and export a PostgreSQL database](import-export-database.md)
- [Connect to your database remotely](connect-remotely.md)
- [Credentials](../../platform/hosts/credentials.md)
- [Applications](../../platform/hosts/applications/index.md)
</content>
