---
title: "Deploy Prefect"
description: "Self-hosted Prefect (Airflow alternative) — password-protected + Postgres"
category: "Automation"
url: https://railway.com/deploy/z8tmK-
---

# Deploy Prefect

Self-hosted Prefect (Airflow alternative) — password-protected + Postgres

**[Deploy Prefect on Railway](https://railway.com/template/z8tmK-)**

- **Creator:** Mark Chen's Projects
- **Category:** Automation
- **Total deploys:** 76

## Template content

### prefect-server

- **Image:** prefecthq/prefect:3.8-python3.12
- **Start command:** `/bin/sh -c "prefect server start --host 0.0.0.0"`
- **Health check:** /api/health
- **Public domain:** Yes

### Postgres https://devicons.railway.app/i/postgresql.svg

- **Image:** ghcr.io/railwayapp-templates/postgres-ssl:18

## Documentation

# Deploy and Host Prefect on Railway

Prefect is a Python orchestration framework for building data pipelines. It turns
an ordinary script into a production workflow with two decorators — `@flow` and
`@task` — and wraps it in scheduling, retries, caching, logging and a UI that shows
you every run.

This template deploys a **self-hosted Prefect server** with its own **PostgreSQL**
database, so your orchestration state lives on infrastructure you control rather
than in a hosted control plane.

**Versions.** Prefect is pinned to the **3.8** line
(`prefecthq/prefect:3.8-python3.12`, currently 3.8.2) and PostgreSQL to **18**
(`postgres-ssl:18`). The pin means a deploy today and a deploy next month give you
the same Prefect minor — the same API, the same UI and the same database schema —
while patch releases still arrive automatically. Check what you are running with
`GET /api/admin/version`.

## About Hosting Prefect

A self-hosted Prefect deployment is two long-running pieces:

- **The Prefect server** — the REST API and the web UI. It stores deployments,
  schedules, flow runs and logs, and serves the dashboard you watch runs in.
- **PostgreSQL** — where all of that state actually lives. Prefect defaults to
  SQLite locally, which is fine on a laptop and unsuitable for a deployed server;
  Postgres is the supported backend for anything long-lived.

This template provisions both and wires them together: the Postgres service gets a
persistent volume so your run history survives redeploys, and the server is given a
public domain with its API mounted at `/api`. Database migrations run automatically
when the server starts, so there is no manual setup step — deploy, wait for the
server to come up, and open the domain.

Note that a Prefect **server** schedules and records work; it does not execute it.
Running flows requires a **worker** attached to a work pool, which you run wherever
your code should execute — another Railway service, your own machine, or CI.

## Why Deploy Prefect on Railway?

Railway is a singular platform to deploy your infrastructure stack. Railway will
host your infrastructure so you don't have to deal with configuration, while
allowing you to vertically and horizontally scale it.

By deploying Prefect on Railway, you are one step closer to supporting a complete
full-stack application with minimal burden. Host your servers, databases, AI
agents, and more on Railway.

Specifically: the server and its database are always-on processes with a persistent
volume — exactly the shape Railway handles well. Both services sit in one project,
on one bill, with per-service logs, metrics and a generated domain, and the database
is attached for you rather than configured by hand.

## Common Use Cases

- **Scheduled ETL / ELT** — pull from an API or a database on a cron, transform,
  load, with retries and visibility when a step fails.
- **Data quality and reporting jobs** — nightly checks, dashboard source refreshes,
  warehouse maintenance.
- **ML pipelines** — recurring feature builds, batch scoring, retraining runs that
  need to be observable and re-runnable.
- **Replacing cron and shell scripts** — the same jobs, but with run history,
  parameters, retries, logs and a UI.
- **A team-shared orchestration UI** — one deployed server that everyone points
  their local Prefect client at.

## Dependencies for Prefect Hosting

- **PostgreSQL** — provisioned by this template.
- **A worker and work pool** — required to *execute* flows; run one wherever your
  code should run and point it at this server.
- **Your flow code** — kept in your own project or Git repository; Prefect pulls it
  at run time via `flow.from_source(...)`, or you bake it into your worker image.

### Deployment Dependencies

- Prefect documentation — https://docs.prefect.io/v3/get-started/index
- Self-hosting guide — https://docs.prefect.io/v3/manage/self-host
- Workers and work pools — https://docs.prefect.io/v3/deploy/infrastructure-concepts/workers
- Security settings — https://docs.prefect.io/v3/advanced/security-settings
- Prefect source — https://github.com/PrefectHQ/prefect

### Implementation Details

Point your local Prefect at the deployed server, then work as usual:

```bash
prefect config set PREFECT_API_URL="https://YOUR-SERVER.up.railway.app/api"
prefect work-pool create --type process Process
prefect worker start -p Process
```

```python
from prefect import flow

if __name__ == "__main__":
    flow.from_source(
        source="https://github.com/YOUR-USER/YOUR-REPO.git",
        entrypoint="flows.py:my_flow",
    ).deploy(name="nightly", work_pool_name="Process", cron="0 3 * * *")
```

**Your server is password-protected by default.** On deploy, a unique random password
is generated for you — nothing is shared between deployments and no default
credentials exist.

Find your credentials in the Railway dashboard: open the **prefect-server** service,
go to **Variables**, and read `PREFECT_SERVER_API_AUTH_STRING`. The value has the form
`admin:PASSWORD` — `admin` is the username, the rest is your password. The browser
will prompt you for them the first time you open the UI.

Every client and worker needs the same value:

```bash
prefect config set PREFECT_API_AUTH_STRING="admin:YOUR-PASSWORD"
```

One thing to be aware of: the sign-in page itself loads without credentials, but the
API behind it is protected, so no data is readable until you authenticate. To change
the password, edit the variable and redeploy.


## Similar templates

- [N8N Main + Worker](https://railway.com/deploy/n8n-main-worker) — Deploy and Host N8N with Inactive worker.
- [Evolution API with n8n](https://railway.com/deploy/evolution-api-with-n8n) — [Jul'26] WhatsApp automation platform using Evolution API, n8n & PostgreSQL
- [Postgres Backup](https://railway.com/deploy/postgres-s3-backups) — Cron-based PostgreSQL backup to bucket storage

Open this page in a browser: https://railway.com/deploy/z8tmK-
