# How to Set Up Docker Deployment with PostgreSQL for Routa: A Complete Guide

> Easily deploy Routa with PostgreSQL using Docker. Switch from SQLite to PostgreSQL with simple environment variables. Get the complete setup guide.

- Repository: [Fengda Huang/routa](https://github.com/phodal/routa)
- Tags: how-to-guide
- Published: 2026-05-26

---

**Routa supports PostgreSQL in Docker by setting `ROUTA_DB_DRIVER=postgres` and providing a `DATABASE_URL`, enabling seamless switching from the default SQLite configuration through environment variables alone.**

Routa is a production-ready Next.js application that abstracts database access through a driver-based architecture, allowing you to deploy with SQLite for development or PostgreSQL for production workloads. Setting up Docker deployment with PostgreSQL for Routa requires minimal configuration—just two environment variables and optionally leveraging the built-in Docker Compose profiles for automated database provisioning.

## Understanding the Database Architecture

Routa's database selection happens at runtime in [`src/core/routa-system.ts`](https://github.com/phodal/routa/blob/main/src/core/routa-system.ts), which implements a factory pattern that instantiates the appropriate storage driver based on the `ROUTA_DB_DRIVER` environment variable. By default, the `Dockerfile` sets `ROUTA_DB_DRIVER=sqlite`, but the system supports `postgres` as an alternative without rebuilding the container.

When `ROUTA_DB_DRIVER=postgres` is set, Routa uses the implementation in [`src/core/db/index.ts`](https://github.com/phodal/routa/blob/main/src/core/db/index.ts), which leverages `drizzle-orm/postgres-js` to manage database connections via the standard `DATABASE_URL` connection string.

## Deploying with the PostgreSQL Docker Profile

The fastest way to run Routa with PostgreSQL is using the `postgres` profile defined in [`docker-compose.yml`](https://github.com/phodal/routa/blob/main/docker-compose.yml). This configuration spins up three coordinated services:

- **app**: The Next.js application container that reads `ROUTA_DB_DRIVER` and `DATABASE_URL` at startup
- **migrate**: A one-shot container that runs `npm run db:push` to apply schema migrations
- **postgres**: A `postgres:16-alpine` container with credentials configurable via environment variables

The `app` service includes a `depends_on` condition with a healthcheck that ensures the database is ready before the application attempts to connect.

To deploy using the bundled PostgreSQL container:

```bash
docker compose --profile postgres up --detach

```

This command automatically generates the `DATABASE_URL` to point at the internal `postgres` service and sets `ROUTA_DB_DRIVER=postgres`.

## Configuring Environment Variables

The switch between SQLite and PostgreSQL is controlled by two critical environment variables exposed in the `Dockerfile`:

1. **`ROUTA_DB_DRIVER`**: Must be set to `postgres` to enable the PostgreSQL driver instead of the default SQLite implementation
2. **`DATABASE_URL`**: A standard PostgreSQL connection string (e.g., `postgresql://user:pass@host:5432/db`)

These variables are consumed by the driver factory in [`src/core/routa-system.ts`](https://github.com/phodal/routa/blob/main/src/core/routa-system.ts) and the connection logic in [`src/core/db/index.ts`](https://github.com/phodal/routa/blob/main/src/core/db/index.ts). You can override these via a `.env` file or directly in your Docker Compose configuration.

## Using an External PostgreSQL Server

If you prefer using an existing PostgreSQL instance rather than the bundled container, omit the `postgres` profile and provide your connection details:

```bash

# .env

ROUTA_DB_DRIVER=postgres
DATABASE_URL=postgresql://myuser:mypassword@mydb.example.com:5432/routa

docker compose up --detach

```

In this configuration, the `app` service still receives the environment variables but connects to your external database server instead of the containerized Postgres service.

## Managing Database Migrations

When running with PostgreSQL, schema changes must be applied using the `migrate` service. After updating your schema or deploying a new version, run:

```bash
docker compose --profile postgres run --rm migrate

```

This executes `npm run db:push` against the configured `DATABASE_URL`, ensuring your database schema matches the application requirements before the app container restarts.

## Default SQLite Deployment (No Database Required)

For development or lightweight deployments, Routa runs with SQLite by default, requiring no external database configuration:

```bash
docker compose up --detach

```

This uses the built-in file-based storage configured in [`src/core/routa-system.ts`](https://github.com/phodal/routa/blob/main/src/core/routa-system.ts) without requiring the `postgres` profile or additional environment variables.

## Key Implementation Files

Understanding these source files helps troubleshoot deployment issues:

- **`Dockerfile`**: Multi-stage build that sets `ROUTA_DB_DRIVER=sqlite` by default and exposes the `DATABASE_URL` environment variable
- **[`docker-compose.yml`](https://github.com/phodal/routa/blob/main/docker-compose.yml)**: Defines service orchestration, healthchecks, and the `postgres` profile that wires the three-service stack together
- **[`src/core/routa-system.ts`](https://github.com/phodal/routa/blob/main/src/core/routa-system.ts)**: Central factory that selects between SQLite and PostgreSQL drivers based on environment variables
- **[`src/core/db/index.ts`](https://github.com/phodal/routa/blob/main/src/core/db/index.ts)**: Implements the PostgreSQL driver using `drizzle-orm/postgres-js` and handles connection pooling

## Summary

- Routa's [`src/core/routa-system.ts`](https://github.com/phodal/routa/blob/main/src/core/routa-system.ts) factory selects database drivers based on the `ROUTA_DB_DRIVER` environment variable
- Set `ROUTA_DB_DRIVER=postgres` and provide a `DATABASE_URL` to switch from SQLite to PostgreSQL
- Use `docker compose --profile postgres up --detach` to run the complete stack including a PostgreSQL 16 container
- Run `docker compose --profile postgres run --rm migrate` to apply database schema changes
- For external databases, omit the profile and set `DATABASE_URL` to point to your existing PostgreSQL server

## Frequently Asked Questions

### Does Routa require code changes to switch from SQLite to PostgreSQL?

No code changes are required. The application uses a factory pattern in [`src/core/routa-system.ts`](https://github.com/phodal/routa/blob/main/src/core/routa-system.ts) that selects the storage implementation at runtime based on the `ROUTA_DB_DRIVER` environment variable. Simply changing this value from `sqlite` to `postgres` and providing a valid `DATABASE_URL` switches the data layer transparently.

### What PostgreSQL version does the Docker Compose profile use?

The `postgres` profile in [`docker-compose.yml`](https://github.com/phodal/routa/blob/main/docker-compose.yml) uses the official `postgres:16-alpine` image. You can override this version by modifying the image tag in the Compose file or setting the `POSTGRES_PASSWORD` environment variable to customize credentials while keeping the default image.

### How do I run database migrations in a Docker environment?

Routa provides a dedicated `migrate` service in [`docker-compose.yml`](https://github.com/phodal/routa/blob/main/docker-compose.yml) that runs `npm run db:push` against your configured `DATABASE_URL`. Execute `docker compose --profile postgres run --rm migrate` to apply schema changes. This is particularly important when upgrading Routa versions or after modifying database schemas.

### Can I use Routa with an external PostgreSQL database?

Yes. If you have an existing PostgreSQL server, set `ROUTA_DB_DRIVER=postgres` and provide the full connection string in `DATABASE_URL` via a `.env` file or environment configuration. Run `docker compose up --detach` without the `postgres` profile, and the application will connect to your external database instead of starting a containerized instance.