- Published on
How to Build a REST API with FastAPI and PostgreSQL (2026)
Building a REST API (Representational State Transfer Application Programming Interface) with FastAPI and PostgreSQL allows you to create high-performance web services that store data permanently in a database. By following this guide, you can set up a functional backend in under 30 minutes using Python 3.14 and SQLAlchemy 2.0. This combination is a popular choice for modern developers because it handles thousands of requests per second while keeping your code clean and easy to read.
Why choose FastAPI and PostgreSQL for your project?
FastAPI is a modern web framework that uses Python's type hints (labels that tell Python what kind of data to expect) to validate your data automatically. This means if you expect a number but receive text, FastAPI will catch the error before your code even runs. It also generates interactive documentation for you, so you can test your API directly in the browser without writing extra code.
PostgreSQL is a powerful, open-source relational database (a system that organizes data into tables with rows and columns). Unlike simple text files, PostgreSQL can handle massive amounts of data and complex relationships between different types of information. It is the industry standard for reliability and data integrity, making it the perfect partner for a fast framework like FastAPI.
Using these tools together creates a "stack" (a collection of software used to build an application) that scales easily. Whether you are building a simple to-do list or a complex backend for an AI agent powered by Claude 4.5, this setup provides the stability you need. We have found that starting with these professional-grade tools early on saves you from painful migrations later when your project grows.
What do you need to get started?
Before writing any code, you need to ensure your computer has the right environment. You will need a code editor like VS Code and a terminal (the text-based interface used to run commands).
What You'll Need:
- Python 3.14+: The latest stable version of the Python programming language.
- PostgreSQL: Download and install it from the official site.
- Pip: The package installer for Python, which usually comes with your Python installation.
- A Virtual Environment: A private folder for your project's tools so they don't interfere with other projects.
To create your virtual environment, open your terminal and run:
# Create the environment folder
python -m venv venv
# Activate it (Windows)
venv\Scripts\activate
# Activate it (Mac/Linux)
source venv/bin/activate
What you should see: Your terminal prompt should now show (venv) at the beginning, indicating you are working inside your protected project space.
How do you install the necessary libraries?
You need a few specific libraries (collections of pre-written code) to help Python talk to the database and handle web requests. We will use psycopg3 as the database driver (the translator between Python and PostgreSQL).
Run this command in your terminal:
pip install fastapi[standard] sqlalchemy psycopg
The fastapi[standard] package includes Uvicorn, which is a lightning-fast web server that hosts your API. SQLAlchemy is an ORM (Object Relational Mapper), which lets you interact with your database using Python objects instead of writing raw SQL (Structured Query Language). This makes your code much safer and easier to maintain.
How do you connect Python to PostgreSQL?
The first step in your code is defining how to connect to the database. You will create a file named database.py to hold these settings. This file tells SQLAlchemy where to find your PostgreSQL server and how to log in.
from sqlalchemy import create_url
from sqlalchemy.orm import DeclarativeBase, sessionmaker
from sqlalchemy import create_engine
# Replace 'user', 'password', and 'dbname' with your actual Postgres details
DATABASE_URL = "postgresql+psycopg://user:password@localhost:5432/dbname"
# The engine is the central source of connections to your database
engine = create_engine(DATABASE_URL)
# This creates a "Session" class which we use to talk to the database
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
# This is the base class that our data models will inherit from
class Base(DeclarativeBase):
pass
Don't worry if the connection string looks confusing. It follows a standard format: driver://username:password@host:port/database_name. If you just installed PostgreSQL, your default username is likely postgres.
How do you define your data structure?
In a relational database, you must define the "shape" of your data before you can save it. This is called a Model. Create a file named models.py to define what a "User" or an "Item" looks like in your application.
from sqlalchemy.orm import Mapped, mapped_column
from .database import Base
class Item(Base):
__tablename__ = "items"
# Mapped and mapped_column are modern SQLAlchemy 2.0 features
id: Mapped[int] = mapped_column(primary_key=True, index=True)
title: Mapped[str] = mapped_column(index=True)
description: Mapped[str | None] = mapped_column(default=None)
In this example, id is the primary key (a unique identifier for every row). By using Python type hints like Mapped[str], you are telling SQLAlchemy exactly what kind of data should live in each column. This prevents errors where someone might try to save a number in a text field.
How do you build the FastAPI routes?
Now you can create the actual API endpoints (the URLs people visit to get data). Create a file named main.py. This is where you will define your logic for creating and reading items from the database.
from fastapi import FastAPI, Depends, HTTPException
from sqlalchemy.orm import Session
from . import models, database
# Initialize the FastAPI app
app = FastAPI()
# Create the database tables automatically
models.Base.metadata.create_all(bind=database.engine)
# This helper function manages the database connection for each request
def get_db():
db = database.SessionLocal()
try:
yield db
finally:
db.close()
@app.get("/items/")
def read_items(db: Session = Depends(get_db)):
# This queries the database for all items
return db.query(models.Item).all()
@app.post("/items/")
def create_item(title: str, description: str, db: Session = Depends(get_db)):
# This creates a new Python object based on our model
new_item = models.Item(title=title, description=description)
db.add(new_item)
db.commit() # This saves the changes to the database
db.refresh(new_item) # This updates our object with the new ID from the DB
return new_item
The @app.get and @app.post lines are called decorators. They tell FastAPI which URL corresponds to which function. When someone sends a "POST" request to /items/, FastAPI runs the create_item function.
How do you run and test your API?
Now it is time to see your work in action. Go back to your terminal and run the following command:
fastapi dev main.py
What you should see: Your terminal will show a message saying "Uvicorn running on http://127.0.0.1:8000". Open your browser and go to http://127.0.0.1:8000/docs.
This page is the interactive documentation we mentioned earlier. You can click on the "POST" button, select "Try it out," enter some data, and click "Execute." You will see a success message and your data will be saved permanently in PostgreSQL.
What are some common gotchas to watch out for?
It is normal to run into a few hurdles when setting up a database for the first time. One frequent issue is the "Connection Refused" error. This usually means your PostgreSQL server isn't running or your username and password in DATABASE_URL are incorrect.
Another common mistake is forgetting to call db.commit(). In SQLAlchemy, changes are not saved to the database until you explicitly commit them. If you restart your server and find your data is gone, check if you missed this step in your "POST" routes.
Finally, ensure you are using the modern SQLAlchemy 2.0 syntax. Older tutorials might show you declarative_base(), but in 2026, we use the DeclarativeBase class. This newer method provides better support for modern Python tools and AI coding assistants like GPT-5, which rely on clear type definitions to help you debug.
Next Steps
Now that you have a working API, you can expand it by adding more complex relationships, like connecting "Users" to "Items." You might also explore Pydantic schemas, which allow you to define even stricter rules for the data your API accepts.
As you build more advanced projects, consider how this API could serve as the "brain" for other applications. For example, a solopreneur could use this exact setup to store memories for an AI agent powered by Claude 4.5. The possibilities are endless once you have a reliable way to store and retrieve data.
For more detailed guides, visit the official FastAPI documentation.