Skip to content

convox-examples/fastapi-postgres

Repository files navigation

FastAPI + PostgreSQL

A production-ready REST API using FastAPI and PostgreSQL, deployed to Convox in minutes.

FastAPI is one of the fastest-growing Python web frameworks — type-safe, with automatic OpenAPI documentation out of the box, and one of the highest-performing Python options for building APIs. Paired with PostgreSQL for persistent storage, containerized with Docker, and deployed to Convox, this stack gives you a working API backend with managed infrastructure and zero Kubernetes configuration.

This example builds a task management API with full CRUD, input validation, health checks, and interactive Swagger docs. Use it as a starting point for internal tools, microservice backends, data-driven web apps, or any project where you need a Python API with a relational database.

Deploy to Convox

Make sure you have a Convox account and a rack set up.

# Clone the repo
git clone https://github.com/convox-examples/fastapi-postgres.git
cd fastapi-postgres

# Create the app and deploy
convox apps create fastapi-postgres --wait
convox deploy --wait

# Verify it's running
convox services

You should see output like:

SERVICE  DOMAIN                                         PORTS
web      web.fastapi-postgres.your-router.convox.cloud  443:8000

Open the domain in your browser to see the interactive Swagger docs at /docs, or test with curl:

curl https://web.fastapi-postgres.<your-router>.convox.cloud/health
# {"status": "healthy"}

What's Included

  • FastAPI with type-safe request/response models and auto-generated OpenAPI docs at /docs
  • PostgreSQL provisioned automatically — Convox creates and links the database with no manual setup
  • SQLModel ORM combining SQLAlchemy's power with Pydantic's validation in a single model definition
  • Health check that verifies database connectivity, used by Convox for automated restarts
  • Connection pooling with pool_pre_ping for resilience across database restarts
  • Startup retry logic that handles the database still initializing on first deploy
  • Input validation with length limits and type checking, returning clear error messages

API Usage

The API provides full CRUD operations for a task resource. Every endpoint returns JSON.

Create a task

curl -X POST https://<your-domain>/tasks \
  -H "Content-Type: application/json" \
  -d '{"title": "Set up CI pipeline", "description": "Configure GitHub Actions for the new service"}'
{
  "title": "Set up CI pipeline",
  "description": "Configure GitHub Actions for the new service",
  "completed": false,
  "id": 1,
  "created_at": "2026-04-15T18:09:47.181492"
}

List tasks

curl https://<your-domain>/tasks
[
  {
    "title": "Set up CI pipeline",
    "description": "Configure GitHub Actions for the new service",
    "completed": false,
    "id": 1,
    "created_at": "2026-04-15T18:09:47.181492"
  }
]

Supports pagination with ?offset=0&limit=20.

Update a task

Partial updates — only send the fields you want to change:

curl -X PUT https://<your-domain>/tasks/1 \
  -H "Content-Type: application/json" \
  -d '{"completed": true}'
{
  "title": "Set up CI pipeline",
  "description": "Configure GitHub Actions for the new service",
  "completed": true,
  "id": 1,
  "created_at": "2026-04-15T18:09:47.181492"
}

Delete a task

curl -X DELETE https://<your-domain>/tasks/1
{"deleted": true}

Validation

FastAPI validates all request data using Pydantic models. Missing or invalid fields return a 422 response with details:

curl -X POST https://<your-domain>/tasks \
  -H "Content-Type: application/json" \
  -d '{}'
{
  "detail": [
    {
      "type": "missing",
      "loc": ["body", "title"],
      "msg": "Field required"
    }
  ]
}

All Endpoints

Method Path Description
GET / API info and available routes
GET /health Health check (verifies DB connection)
GET /docs Interactive Swagger UI documentation
POST /tasks Create a task
GET /tasks List tasks (supports offset and limit)
GET /tasks/{id} Get a single task
PUT /tasks/{id} Update a task (partial updates supported)
DELETE /tasks/{id} Delete a task

How It Works

The convox.yml defines one service and one resource:

resources:
  database:
    type: postgres

services:
  web:
    build: .
    port: 8000
    health:
      path: /health
      grace: 15
    resources:
      - database
    scale:
      count: 1
      memory: 512

When you run convox deploy, Convox:

  1. Builds the Docker image from the Dockerfile
  2. Provisions a PostgreSQL database (if it doesn't already exist)
  3. Injects DATABASE_URL into the web service environment automatically
  4. Starts the service and begins health checking /health
  5. Routes HTTPS traffic to port 8000 — TLS is handled for you

The application creates its database tables on startup using SQLModel's create_all(). No migration tool is needed for this example, but see Extending This Example for adding Alembic when your schema evolves.

Local Development

Run the API locally with a PostgreSQL instance (via Docker or a local install):

# Start a local Postgres (if you don't have one running)
docker run -d --name pg -e POSTGRES_PASSWORD=password -p 5432:5432 postgres:16

# Set up a virtual environment
python -m venv .venv
source .venv/bin/activate

# Set the connection string (see .env.example for reference)
export DATABASE_URL=postgresql://postgres:password@localhost:5432/postgres

# Install dependencies and run
pip install -r requirements.txt
uvicorn main:app --reload --port 8000

If port 5432 is already in use, change -p 5432:5432 to -p 5433:5432 and update the port in DATABASE_URL accordingly.

The API is now running at http://localhost:8000. Open http://localhost:8000/docs for the interactive Swagger UI.

Configuration

Environment Variables

Variable Description Default
DATABASE_URL PostgreSQL connection string Provided by Convox postgres resource

Scaling

Adjust the number of containers and memory allocation:

convox scale web --count 2 --memory 1024

Production Database Configuration

The default type: postgres resource runs a containerized PostgreSQL suitable for development and testing. For production workloads on AWS, use rds-postgres to provision a managed RDS instance:

resources:
  database:
    type: rds-postgres
    options:
      class: db.t3.medium
      storage: 100
      encrypted: true
      durable: true
      deletionProtection: true
      backupRetentionPeriod: 7

services:
  web:
    build: .
    port: 8000
    health:
      path: /health
      grace: 15
    resources:
      - database
    scale:
      count: 2
      memory: 512

Key production options:

Option Description
class RDS instance type (e.g., db.t3.medium, db.m5.large)
storage Allocated storage in GB
encrypted Enable storage encryption
durable Multi-AZ deployment for high availability
deletionProtection Prevent accidental database deletion
backupRetentionPeriod Days to retain automated backups

See the Convox PostgreSQL resource documentation for all available options.

Extending This Example

This example is deliberately minimal. Here are common next steps when building on it:

  • Database migrations — Add Alembic to manage schema changes. SQLModel's create_all() works for initial setup, but Alembic tracks incremental migrations as your models evolve.
  • Authentication — FastAPI integrates with OAuth2 and JWT via its security utilities. Add token-based auth without changing the existing route structure.
  • Background tasks — Use FastAPI's BackgroundTasks for quick async work, or add a Convox timer resource for scheduled jobs like cleanup or report generation.
  • Multiple services — Split into separate services in convox.yml (e.g., an API service and a worker). Each gets its own scaling and resource allocation.
  • Custom domain — Point your domain at the Convox router and configure TLS. See the custom domains guide.

Project Structure

├── main.py           # FastAPI application and route handlers
├── models.py         # SQLModel database and API models
├── database.py       # Database engine, session, and health check
├── requirements.txt  # Python dependencies
├── Dockerfile        # Container image definition
├── convox.yml        # Convox deployment configuration
└── .env.example      # Environment variable reference for local dev

Learn More

About

FastAPI + PostgreSQL task management API example

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors