Build A Robust Backend: FastAPI, PostgreSQL, & Supabase
Hey guys! Let's dive into setting up a solid backend infrastructure using FastAPI, PostgreSQL, and Supabase. This will cover everything from the initial API structure and database models to proper configuration management, ensuring we have a scalable and reliable foundation for our applications. We will address key areas such as API endpoints, database persistence, error handling, and comprehensive documentation with a focus on building a high-quality, SEO-optimized article.
βοΈ Overview of the Project
Our goal is to build a robust backend capable of handling various business logic operations using RESTful API endpoints. We'll leverage PostgreSQL, managed through Supabase, for database persistence, utilizing best practices in ORM (Object-Relational Mapping) patterns. The project will incorporate environment-specific configurations to handle different deployment scenarios (development, staging, production). Moreover, we will focus on error handling, robust logging, and generating thorough API documentation using Swagger/OpenAPI to make it easy to understand and use.
π€ Defining the Problem Statement
We need a backend that is more than just functional; it needs to be scalable, maintainable, and well-documented. The key problems we are addressing are:
- RESTful API endpoints: Creating a structured and efficient way to expose business logic.
- Database persistence: Ensuring data is stored reliably, with efficient querying and data integrity using proper ORM patterns.
- Configuration management: Managing settings across multiple environments (dev, staging, production) is essential to the project's scalability.
- Error handling and logging: Implementing robust error handling and comprehensive logging to quickly identify and fix issues.
- API documentation: Providing clear and concise documentation (using Swagger/OpenAPI) to facilitate easy integration and understanding of the API.
π‘ Proposed Solution
We will construct a FastAPI application with several key components to address the challenges outlined above. This includes the following technologies:
- SQLAlchemy ORM: This will manage database operations, providing an abstraction layer that simplifies database interactions.
- Alembic: Used for database migrations, allowing us to manage and evolve the database schema over time.
- Pydantic: This library will be used for request and response validation, ensuring data integrity.
- Supabase client integration: Utilizing Supabase for user authentication and handling storage features.
- Environment-based configuration: Using Pydantic-settings to manage settings for different environments (development, staging, production).
π οΈ Technical Approach and Implementation
Let's break down the technical approach step-by-step, including the project structure, database models, and more.
ποΈ Project Structure Explained
Hereβs how we will structure our backend project to keep things organized:
backend/
βββ app/
β βββ __init__.py
β βββ main.py # FastAPI application entry point
β βββ config.py # Settings and configuration
β βββ database.py # Database connection and session
β βββ dependencies.py # FastAPI dependencies
β βββ models/ # SQLAlchemy models
β β βββ __init__.py
β β βββ user.py
β β βββ contact.py
β β βββ campaign.py
β β βββ message.py
β βββ schemas/ # Pydantic schemas
β β βββ __init__.py
β β βββ user.py
β β βββ contact.py
β β βββ campaign.py
β βββ api/ # API routes
β β βββ __init__.py
β β βββ deps.py # Route dependencies
β β βββ v1/
β β βββ __init__.py
β β βββ users.py
β β βββ contacts.py
β β βββ campaigns.py
β βββ core/ # Core utilities
β βββ __init__.py
β βββ security.py
β βββ logging.py
βββ tests/
β βββ __init__.py
β βββ conftest.py
β βββ api/
βββ alembic/ # Database migrations
β βββ versions/
β βββ env.py
βββ alembic.ini
βββ requirements.txt
βββ requirements-dev.txt
βββ .env.example
This structure organizes the project with clear separation of concerns, making it easier to manage and scale.
π¦ Database Models and ERD (Entity Relationship Diagram)
We will model our data using SQLAlchemy models. Here is the Entity Relationship Diagram:
erDiagram
USER ||--o{ CONTACT : owns
USER ||--o{ CAMPAIGN : creates
CAMPAIGN ||--o{ MESSAGE : contains
CONTACT ||--o{ MESSAGE : receives
USER {
uuid id PK
string email UK
string business_name
string trade_type
string zip_code
int service_radius
string subscription_tier
timestamp created_at
timestamp updated_at
}
CONTACT {
uuid id PK
uuid user_id FK
string business_name
string email
string phone
string trade_type
string website
string source
string status
jsonb metadata
timestamp created_at
}
CAMPAIGN {
uuid id PK
uuid user_id FK
string name
string status
jsonb email_template
jsonb sms_template
timestamp scheduled_at
timestamp created_at
}
MESSAGE {
uuid id PK
uuid campaign_id FK
uuid contact_id FK
string type
string status
string content
timestamp sent_at
timestamp opened_at
timestamp replied_at
}
This diagram outlines the relationships between the User, Contact, Campaign, and Message entities, providing a visual guide to the data structure.
β Defining Acceptance Criteria
To ensure the successful implementation of our backend, we have set the following criteria.
βοΈ Core Setup
- Initialize FastAPI application in
app/main.py - Set up CORS (Cross-Origin Resource Sharing) middleware to integrate with the frontend.
- Configure Supabase client connection.
- Implement environment-based configuration using Pydantic Settings.
- Add a health check endpoint (
/health,/health/db).
πΎ Database Layer
- Create SQLAlchemy models for User, Contact, Campaign, and Message.
- Set up database connection pooling.
- Initialize Alembic for migrations.
- Create an initial migration with all models.
- Add a database session dependency for routes.
π¦ API Structure
- Implement API versioning (
/api/v1). - Create base response schemas with Pydantic.
- Add request validation middleware.
- Set up automatic OpenAPI/Swagger documentation.
- Implement consistent error handling.
βοΈ Configuration Management
- Create
.env.examplewith all required variables:DATABASE_URL,SUPABASE_URL,SUPABASE_KEY,SUPABASE_JWT_SECRET,ENVIRONMENT(dev/staging/prod). - Add config validation on startup.
- Implement a secrets management strategy.
π§ͺ Testing Infrastructure
- Set up pytest with async support.
- Create test database fixtures.
- Add an integration test for database connection.
- Implement an API client fixture for endpoint testing.
π Documentation
- Add docstrings to all models and schemas.
- Configure Swagger UI customization.
- Add API usage examples in docstrings.
π Success Metrics
Our backend implementation will be considered successful if the following conditions are met:
- The FastAPI server starts without errors.
- All database migrations run successfully.
- API docs are accessible at
/docs. - Health check endpoints return 200 (OK).
- The test suite passes with >80% code coverage.
π§° Dependencies and Prerequisites
Here are the dependencies and prerequisites needed to build this project.
Depends on:
- Issue #1 (Project Foundation) - The repository structure must already exist.
Required:
- A Supabase project created with a PostgreSQL database.
- The database URL and credentials configured.
π Implementation Notes and Code Snippets
Below are implementation notes and code snippets to give you a head start.
π app/main.py
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.config import settings
from app.api.v1 import users, contacts, campaigns
app = FastAPI(
title="TradePartner AI API",
description="B2B partnership automation for local trades",
version="1.0.0"
)
# CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=settings.ALLOWED_ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Include routers
app.include_router(users.router, prefix="/api/v1", tags=["users"])
app.include_router(contacts.router, prefix="/api/v1", tags=["contacts"])
app.include_router(campaigns.router, prefix="/api/v1", tags=["campaigns"])
@app.get("/health")
async def health_check():
return {"status": "healthy"}
This main.py file initializes the FastAPI application, sets up CORS middleware, includes API routers, and defines a health check endpoint.
π§βπ» app/models/user.py
from sqlalchemy import Column, String, Integer, DateTime
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.sql import func
import uuid
from app.database import Base
class User(Base):
__tablename__ = "users"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
email = Column(String, unique=True, index=True, nullable=False)
business_name = Column(String, nullable=False)
trade_type = Column(String, nullable=False)
zip_code = Column(String(10), nullable=False)
service_radius = Column(Integer, default=25)
subscription_tier = Column(String, default="free")
created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
This code snippet defines the User model using SQLAlchemy, including columns for user details like email, business name, and more.
π References and Research
Here are some resources for further research and understanding:
π FastAPI Documentation
- FastAPI: https://fastapi.tiangolo.com/
- SQLAlchemy 2.0: https://docs.sqlalchemy.org/en/20/
- Alembic: https://alembic.sqlalchemy.org/
- Pydantic Settings: https://docs.pydantic.dev/latest/concepts/pydantic_settings/
π‘ Architecture Reference
/scripts/system_architecture_diagram.txt- Backend architecture (example file)./scripts/PRD.txt- Section 5 (Functional Requirements) (example file).
π§ Best Practices
- FastAPI project structure patterns
- SQLAlchemy async patterns with PostgreSQL
- Database migration strategies with Alembic
Estimate: 2-3 days
That's it, guys! With these steps, we can set up a robust, scalable, and well-documented backend. Happy coding!