FastAPI

How to Connect FastAPI to PostgreSQL (Step-by-Step Guide)

Thirdy Gayares
3 min read
FastAPI History Banner

PostgreSQL Prerequisites

Before connecting FastAPI to PostgreSQL, make sure you already installed PostgreSQL and created a database + table. This way, your API has real data to read and write.

Download PostgreSQL here: https://www.postgresql.org/download/

Create Database

Create database in PostgreSQL (pgAdmin)

Create Employee Table

Create employee table in PostgreSQL

We will create an employee table with practical fields like name, email, department, salary, and hired_at. This mirrors how real companies store employee records and gives us a solid dataset for testing CRUD endpoints (Create, Read, Update, Delete) in FastAPI.

CREATE TABLE employee (
  employee_id BIGSERIAL PRIMARY KEY,
  first_name  VARCHAR(50)  NOT NULL,
  last_name   VARCHAR(50)  NOT NULL,
  email       VARCHAR(120) UNIQUE NOT NULL,
  department  VARCHAR(80)  NOT NULL,
  salary      NUMERIC(12,2) NOT NULL DEFAULT 0,
  hired_at    TIMESTAMPTZ  NOT NULL DEFAULT NOW()
);

Create Sample Data

Insert sample employee data

Now that the table exists, let’s insert sample rows so you can instantly test if your database connection works.

INSERT INTO employee (first_name, last_name, email, department, salary)
VALUES
('Jose', 'Iliga', '[email protected]', 'Engineering', 85000),
('Anna', 'Reyes', '[email protected]', 'HR', 45000);

Install Python Libraries

pip install fastapi sqlmodel psycopg uvicorn

Here is a simple explanation of each library:

Library NameDefinition
fastapiPython framework for building APIs fast (with automatic Swagger docs).
sqlmodelLibrary for defining database models and running SQL queries using Python classes (SQLAlchemy + Pydantic).
psycopgPostgreSQL driver that lets Python connect and talk to Postgres.
uvicornServer that runs your FastAPI app locally (best for development).

Create a Database Configuration

Create a file named main.py and add your database configuration:

from sqlmodel import create_engine, Session

# Database configuration -- add this on .env
DATABASE_USERNAME = "joseiiigayares"
PASSWORD = ""
DATABASE_HOST = "localhost"
DATABASE_PORT = "5432"
DATABASE_NAME = "fastapi_db"

DATABASE_URL = f"postgresql+psycopg://{DATABASE_USERNAME}:{PASSWORD}@{DATABASE_HOST}:{DATABASE_PORT}/{DATABASE_NAME}"

# Create the database engine
engine = create_engine(
    DATABASE_URL,
    echo=True, # Set to False in production
    pool_pre_ping=True,
    pool_size=20,
    max_overflow=40,
    pool_timeout=30,
)

def get_session():
    with Session(engine) as session:
        try:
            yield session
        except:
            session.rollback()
            raise

Configuration definitions:

NameDescription
DATABASE_USERNAMEAccount used to authenticate to PostgreSQL
PASSWORDPassword for the database account (leave blank if not set)
DATABASE_HOSTServer address where PostgreSQL is running
DATABASE_PORTNetwork port PostgreSQL is listening on (default 5432)
DATABASE_NAMETarget database to connect to
DATABASE_URLFinal connection string used by SQLModel/SQLAlchemy

This configuration does three important things:

  1. Builds DATABASE_URL — tells our app where Postgres is and which database to use
  2. Creates the database engine — manages connections, pooling, and reconnect checks
  3. Provides get_session() — lets FastAPI reuse a DB session safely per request

Check if Working: GET and CREATE Endpoint

Create FastAPI objects

from fastapi import FastAPI, Depends, HTTPException, status
from sqlmodel import SQLModel, Field, Session, create_engine, select
from typing import Optional, List

app = FastAPI(title="Employee CRUD - FastAPI + SQLModel")

Create basic models

class EmployeeBase(SQLModel):
    first_name: str
    last_name: str
    email: str
    department: str
    salary: float = 0


class Employee(EmployeeBase, table=True):
    employee_id: Optional[int] = Field(default=None, primary_key=True)


class EmployeeCreate(EmployeeBase):
    pass

Fetch all employee endpoint

@app.get("/employees", response_model=List[Employee])
def fetch_all_employees(session: Session = Depends(get_session)):
    employees = session.exec(select(Employee)).all()
    return employees

Create employee endpoint

@app.post("/employees", response_model=Employee, status_code=status.HTTP_201_CREATED)
def create_employee(
    payload: EmployeeCreate,
    session: Session = Depends(get_session),
):
    employee = Employee.model_validate(payload)
    session.add(employee)
    session.commit()
    session.refresh(employee)
    return employee

Run FastAPI

uvicorn main:app --reload

Test in Swagger Docs

Open Swagger UI at http://127.0.0.1:8000/docs to test your API quickly without Postman.

  • Test Create Employee and verify the response (expect 201 Created).
  • Confirm the new record is saved by checking your employee table in PostgreSQL.
Swagger UI create employee test
  • Test Fetch All Employees to confirm data is being read correctly.
  • Swagger UI fetch all employees test

    We’ve successfully connected FastAPI to PostgreSQL using SQLModel and psycopg, created an employee table, and built working CRUD endpoints. By testing everything in Swagger UI (/docs), we confirmed that our API can create records (POST) and fetch data (GET) from a real Postgres database. From here, we can upgrade this project by adding Update (PUT/PATCH) and Delete (DELETE) endpoints, moving credentials into a .env file, and using migrations (like Alembic) for safer database updates. This setup is a solid foundation for building production-ready FastAPI applications with PostgreSQL.

    Resources

    About the Author

    TG

    Thirdy Gayares

    Passionate developer creating custom solutions for everyone. I specialize in building user-friendly tools that solve real-world problems while maintaining the highest standards of security and privacy.