---
title: Postgres
label: Postgres
order: 50
desc: Payload supports Postgres through an officially supported Drizzle database adapter.
keywords: Postgres, documentation, typescript, Content Management System, cms, headless, javascript, node, react, express
---

To use Payload with Postgres, install the package `@payloadcms/db-postgres`. It leverages Drizzle ORM and `node-postgres` to interact with a Postgres database that you provide.

<Banner>
  The Postgres database adapter is currently in beta. If you would like to help us test this
  package, we'd love to hear if you find any bugs or issues!
</Banner>

It automatically manages changes to your database for you in development mode, and exposes a full suite of migration controls for you to leverage in order to keep other database environments in sync with your schema. DDL transformations are automatically generated.

To configure Payload to use Postgres, pass the `postgresAdapter` to your Payload config as follows:

```ts
import { postgresAdapter } from '@payloadcms/db-postgres'

export default buildConfig({
  // Your config goes here
  collections: [
    // Collections go here
  ],
  // Configure the Postgres adapter here
  db: postgresAdapter({
    // Postgres-specific arguments go here.
    // `pool` is required.
    pool: {
      connectionString: process.env.DATABASE_URI,
    },
  }),
})
```

### Options

| Option                | Description                                                                                                                                                                                           |
|-----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `pool` \*             | [Pool connection options](https://orm.drizzle.team/docs/quick-postgresql/node-postgres) that will be passed to Drizzle and `node-postgres`.                                                           |
| `push`                | Disable Drizzle's [`db push`](https://orm.drizzle.team/kit-docs/overview#prototyping-with-db-push) in development mode. By default, `push` is enabled for development mode only.                      |
| `migrationDir`        | Customize the directory that migrations are stored.                                                                                                                                                   |
| `logger`              | The instance of the logger to be passed to drizzle. By default Payload's will be used.                                                                                                                |
| `schemaName`   | A string for the postgres schema to use, defaults to 'public'.                                                                                                                   |
| `localesSuffix`       | A string appended to the end of table names for storing localized fields. Default is '_locales'.                                                                                                      |
| `relationshipsSuffix` | A string appended to the end of table names for storing relationships. Default is '_rels'.                                                                                                            |
| `versionsSuffix`      | A string appended to the end of table names for storing versions. Defaults to '_v'.                                                                                                                   |



### Access to Drizzle

After Payload is initialized, this adapter will expose the full power of Drizzle to you for use if you need it.

You can access Drizzle as follows:

```text
payload.db.drizzle
```

### Tables, relations, and enums

In addition to exposing Drizzle directly, all of the tables, Drizzle relations, and enum configs are exposed for you via the `payload.db` property as well.

- Tables - `payload.db.tables`
- Enums - `payload.db.enums`
- Relations - `payload.db.relations`

### Prototyping in development mode

Drizzle exposes two ways to work locally in development mode.

The first is [`db push`](https://orm.drizzle.team/kit-docs/overview#prototyping-with-db-push), which automatically pushes changes you make to your Payload config (and therefore, Drizzle schema) to your database so you don't have to manually migrate every time you change your Payload config. This only works in development mode, and should not be mixed with manually running [`migrate`](/docs/database/migrations) commands.

You will be warned if any changes that you make will entail data loss while in development mode. Push is enabled by default, but you can opt out if you'd like.

Alternatively, you can disable `push` and rely solely on migrations to keep your local database in sync with your Payload config.

### Migration workflows

Migrations are extremely powerful thanks to the seamless way that Payload and Drizzle work together. Let's take the following scenario:

1. You are building your Payload config locally, with a local database used for testing.
1. You have left the default setting of `push` enabled, so every time you change your Payload config (add or remove fields, collections, etc.), Drizzle will automatically push changes to your local DB.
1. Once you're done with your changes, or have completed a feature, you can run `npm run payload migrate:create`.
1. Payload and Drizzle will look for any existing migrations, and automatically generate all SQL changes necessary to convert your schema from its prior state into the state of your current Payload config, and store the resulting DDL in a newly created migration.
1. Once you're ready to go to production, you will be able to run `npm run payload migrate` against your production database, which will apply any new migrations that have not yet run.
1. Now your production database is in sync with your Payload config!

<Banner type="warning">
  Warning: do not mix "push" and migrations with your local development database. If you use "push"
  locally, and then try to migrate, Payload will throw a warning, telling you that these two methods
  are not meant to be used interchangeably.
</Banner>
