---
title: "Deploy FastAPI Starter"
description: "FastAPI on Python 3.15 + uv: Postgres, Alembic, OTel, health probes"
category: "Starters"
url: https://railway.com/deploy/fastapi-starter-2
---

# Deploy FastAPI Starter

FastAPI on Python 3.15 + uv: Postgres, Alembic, OTel, health probes

**[Deploy FastAPI Starter on Railway](https://railway.com/template/fastapi-starter-2)**

Machine-readable deploy manifest (JSON, validated by TemplateCI): https://railway.com/deploy/fastapi-starter-2/manifest.json

- **Creator:** wotonews
- **Category:** Starters

## Template content

### fastapi

- **Image:** wotonews/fastapi:v1.1.0

### Postgres

- **Image:** wotonews/postgres:v18.6-1

## Documentation

# Deploy and Host FastAPI

Deploy this FastAPI Starter on Railway and get a production-ready Python 3.15 API with PostgreSQL, Alembic migrations, health probes, and OpenTelemetry telemetry in one click.

## About Hosting

Hosting FastAPI on Railway gives you a managed, usage-based platform for your Python API: automatic TLS, deploys from prebuilt images, vertical and horizontal scaling, built-in observability, and a bundled PostgreSQL 18 database (our hardened image with essential extensions) provisioned alongside your app. This starter runs on the latest stable Python (3.15) with a uv-locked dependency tree, runs database migrations before serving traffic, and reports liveness/readiness so Railway only routes traffic to healthy instances.

## Why Deploy FastAPI Starter on Railway?

This template wires the full production path for you: a hardened multi-stage Docker image (non-root, slim), a bundled PostgreSQL 18 service from our own hardened image (persistent volume, extensions preloaded) with the connection string auto-composed over Railway's private network, additive Alembic migrations executed on boot, native OpenTelemetry traces/metrics/logs flowing into Railway's Observability tab, and JSON structured logging out of the box. Instead of wiring a framework version, database, migrations, health checks, and telemetry yourself, deploy once and start writing endpoints — the reference CRUD resource shows the pattern to copy.

## What's included

| Service | Type | Purpose |
| --- | --- |
| fastapi | Web Service | The FastAPI app: async SQLModel, Alembic on boot, health probes |
| Postgres | Database | PostgreSQL 18 (our hardened image, persistent volume); connection URL auto-composed as `DATABASE_URL` |

## Key features

- **Latest stack**: FastAPI 0.162.4 on Python 3.15.2, uv-locked for reproducible builds
- **PostgreSQL + Alembic**: bundled PostgreSQL 18 service (persistent volume, extensions preloaded), additive migrations run before serving
- **Health probes**: `/healthz` liveness (Railway healthcheck) and `/readyz` DB readiness
- **Native OpenTelemetry**: traces, metrics, and logs export to Railway's OTLP collector — no code needed
- **Production hygiene**: non-root multi-stage image, JSON logging, `WEB_CONCURRENCY` worker scaling, graceful shutdown

## Common Use Cases

- Backend developer launches a production FastAPI API with Postgres in one click
- Team standardizes on a modern, pinned Python API starter with observability built in
- Solo dev prototypes an API locally (uv + SQLite) and ships the same code to Railway
- Anyone needing a reference for async SQLModel, Alembic zero-downtime migrations, and health-probe patterns

## Dependencies for FastAPI

### Deployment Dependencies

| Name | Version | Purpose |
| --- | --- | --- |
| Python | 3.15.2 | Runtime (latest stable) |
| FastAPI | 0.162.4 | Web framework (pinned) |
| uvicorn / fastapi-cli | locked in `uv.lock` | ASGI server via the official `fastapi run` CLI |
| SQLModel + SQLAlchemy async | locked | ORM over asyncpg |
| Alembic | locked | Versioned, additive migrations |
| PostgreSQL | 18 (our image) | Bundled database service with persistent volume |

## Next steps

1. Open the service domain and visit `/docs` — the interactive Swagger UI with the reference CRUD at `/api/v1/items`
2. Create an item via `POST /api/v1/items`, then list with `GET /api/v1/items`
3. Open the Observability tab and watch request spans arrive via OpenTelemetry
4. Copy `app/db/models/item.py` + `app/api/routes/items.py` to add your own resources, then autogenerate a migration

---

# 🐍 Deep Dive — FastAPI Starter

## 📐 Architecture

```mermaid
graph TD
    Client([Client / Frontend]) --&gt; Gateway[Railway Public Domain + TLS]
    Gateway --&gt; Web[fastapi service<br>Python 3.15 · uvicorn workers]
    Web --&gt; PG[(Postgres service<br>auto-provisioned)]
    Web --&gt; OTel[Railway Observability<br>OTLP traces · metrics · logs]
```

## ⚙️ Environment Variables

Wired automatically (no input needed): `DATABASE_URL` is composed from the bundled Postgres service credentials — `postgresql://${{Postgres.POSTGRES_USER}}:${{Postgres.POSTGRES_PASSWORD}}@${{Postgres.RAILWAY_PRIVATE_DOMAIN}}:5432/${{Postgres.POSTGRES_DB}}` — and normalized to the asyncpg driver at runtime. Set `DATABASE_URL` explicitly to use an external database instead.

User-configurable:

| Variable | Default | Description |
| :--- | :--- | :--- |
| **`PORT`** | `8000` | Injected by Railway; the entrypoint binds it automatically. |
| **`WEB_CONCURRENCY`** | `2` | Uvicorn workers (read natively by the FastAPI CLI). Scale with CPU. |
| **`ENVIRONMENT`** | `production` | Environment label (`production`, `staging`, …). |
| **`LOG_LEVEL`** | `info` | `debug` · `info` · `warning` · `error` — logs ship as JSON. |
| **`BACKEND_CORS_ORIGINS`** | *(empty)* | Comma-separated allowed CORS origins. |
| **`RUN_MIGRATIONS`** | `true` | Run `alembic upgrade head` before serving. |
| **`DB_POOL_SIZE` / `DB_MAX_OVERFLOW`** | `10 / 10` | Async connection pool tuning. |
| **`FASTAPI_OTEL_AUTO_CONFIGURE`** | `true` | Native OTel export (active when Railway's OTLP endpoint is present). |

## 🚀 Local Development

Prerequisites: [uv](https://docs.astral.sh/uv/) (installs Python 3.15 automatically).

```bash
git clone  &amp;&amp; cd fastapi
cp .env.example .env

uv sync --all-groups          # resolves uv.lock exactly
uv run fastapi dev            # hot-reload dev server on :8000
uv run pytest                 # test suite (async SQLite — no Postgres needed)
uv run alembic upgrade head   # apply migrations locally
```

Handy commands:

```bash
uv run alembic revision --autogenerate -m "add orders table"   # new migration
uv lock &amp;&amp; uv sync --all-groups                                # after dependency changes
bash e2e/run-tests.sh                                          # full template validation
```

### Shipping to Railway

```bash
railway init    # or link an existing project
railway up      # builds from the Dockerfile (config-as-code in railway.toml)
```

## 🩺 Health &amp; Observability

| Endpoint | Purpose | Behavior |
| :--- | :--- | :--- |
| `/healthz` | Liveness (Railway `healthcheckPath`) | Cheap JSON 200 — never touches the DB. |
| `/readyz` | Readiness | `SELECT 1` round-trip; 503 when the DB is down. |
| `/docs`, `/redoc` | Interactive API docs | Auto-generated OpenAPI. |
| `/api/v1/items` | Reference CRUD | Copy this pattern for your own resources. |

## 🧱 Building Your Own API on Top

1. **New resource** → copy the `app/db/models/item.py` split (Base → table → Create/Update/Public), then `uv run alembic revision --autogenerate -m "…"`.
2. **New endpoints** → add a router under `app/api/routes/`, include it in `app/main.py`.
3. **New config** → add the field to `app/core/config.py`; it becomes an env var automatically.
4. **Migrations stay additive** — nullable columns first, chunked backfills, `CREATE INDEX CONCURRENTLY` on live tables (zero-downtime policy).

## 🧪 End-to-End (E2E) Testing

```bash
bash e2e/run-tests.sh
```

Validates structure, marketplace publish config, manifest wiring (Postgres → `DATABASE_URL`), `uv.lock` freshness, byte-compilation, pytest, Docker build, and a live container smoke probe of `/healthz` + `/docs`. CI runs hadolint + this suite on every push/PR.

---

Maintained by the template publisher. Deployments are eligible for Railway's standard template support flow — questions land in the publisher's Template Queue.


## Similar templates

- [Openfront Gym](https://railway.com/deploy/openfront-gym) — Opensource Mindbody alternative based on Next.js and Keystone.js
- [open-excalidraw](https://railway.com/deploy/open-excalidraw) — Self-hostable collaborative drawing built on Excalidraw
- [Next.js + Prisma + PostgreSQL Starter](https://railway.com/deploy/nextjs-prisma-postgres) — Deploy a Next.js app with Prisma ORM and PostgreSQL in one click.

Open this page in a browser: https://railway.com/deploy/fastapi-starter-2
