First Run Guide¶
Congratulations on setting up the FastAPI Boilerplate! This guide will walk you through testing your installation, understanding the basics, and making your first customizations.
Verification Checklist¶
Before diving deeper, let's verify everything is working correctly.
1. Check All Services¶
Ensure all services are running:
# For Docker Compose users docker compose ps # Expected output: # NAME COMMAND SERVICE STATUS # fastapi-boilerplate-web-1 "uvicorn app.main:app…" web running # fastapi-boilerplate-db-1 "docker-entrypoint.s…" db running # fastapi-boilerplate-redis-1 "docker-entrypoint.s…" redis running # fastapi-boilerplate-worker-1 "arq src.app.core.wo…" worker running 2. Test API Endpoints¶
Visit these URLs to confirm your API is working:
API Documentation: - Swagger UI: http://localhost:8000/docs - ReDoc: http://localhost:8000/redoc
Health Check:
Expected response:
{ "status":"healthy", "environment":"local", "version":"0.1.0", "timestamp":"2025-10-21T14:40:14+00:00" } Ready Check:
Expected response:
{ "status":"healthy", "environment":"local", "version":"0.1.0", "app":"healthy", "database":"healthy", "redis":"healthy", "timestamp":"2025-10-21T14:40:47+00:00" } 3. Database Connection¶
Check if the database tables were created:
# For Docker Compose docker compose exec db psql -U postgres -d myapp -c "\dt" # You should see tables like: # public | users | table | postgres # public | posts | table | postgres # public | tiers | table | postgres # public | rate_limits | table | postgres 4. Redis Connection¶
Test Redis connectivity:
Initial Setup¶
Before testing features, you need to create the first superuser and tier.
Creating the First Superuser¶
Prerequisites
Make sure the database and tables are created before running create_superuser. The database should be running and the API should have started at least once.
Using Docker Compose¶
If using Docker Compose, uncomment this section in your docker-compose.yml:
#-------- uncomment to create first superuser -------- create_superuser: build: context: . dockerfile: Dockerfile env_file: - ./src/.env depends_on: - db command: python -m src.scripts.create_first_superuser volumes: - ./src:/code/src Then run:
# Start services and run create_superuser automatically docker compose up -d # Or run it manually docker compose run --rm create_superuser # Stop the create_superuser service when done docker compose stop create_superuser From Scratch¶
If running manually, use:
Creating the First Tier¶
Prerequisites
Make sure the database and tables are created before running create_tier.
Using Docker Compose¶
Uncomment the create_tier service in docker-compose.yml and run:
From Scratch¶
Testing Core Features¶
Let's test the main features of your API.
Authentication Flow¶
1. Login with Admin User¶
Use the admin credentials you set in your .env file:
curl -X POST "http://localhost:8000/api/v1/login" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "username=admin&password=your_admin_password" You should receive a response like:
{ "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...", "token_type": "bearer", "refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." } 2. Create a New User¶
curl -X POST "http://localhost:8000/api/v1/users" \ -H "Content-Type: application/json" \ -d '{ "name": "John Doe", "username": "johndoe", "email": "john@example.com", "password": "securepassword123" }' 3. Test Protected Endpoint¶
Use the access token from step 1:
curl -X GET "http://localhost:8000/api/v1/users/me" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN_HERE" CRUD Operations¶
1. Create a Post¶
curl -X POST "http://localhost:8000/api/v1/posts" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN_HERE" \ -d '{ "title": "My First Post", "content": "This is the content of my first post!" }' 2. Get All Posts¶
curl -X GET "http://localhost:8000/api/v1/posts" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN_HERE" 3. Get Posts with Pagination¶
curl -X GET "http://localhost:8000/api/v1/posts?page=1&items_per_page=5" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN_HERE" Background Tasks¶
Test the job queue system:
1. Submit a Background Task¶
curl -X POST "http://localhost:8000/api/v1/tasks/task?message=hello" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN_HERE" Response:
2. Check Task Status¶
curl -X GET "http://localhost:8000/api/v1/tasks/task/550e8400-e29b-41d4-a716-446655440000" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN_HERE" Caching¶
Test the caching system:
1. Make a Cached Request¶
# First request (cache miss) curl -X GET "http://localhost:8000/api/v1/users/johndoe" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN_HERE" \ -w "Time: %{time_total}s\n" # Second request (cache hit - should be faster) curl -X GET "http://localhost:8000/api/v1/users/johndoe" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN_HERE" \ -w "Time: %{time_total}s\n" Your First Customization¶
Let's create a simple custom endpoint to see how easy it is to extend the boilerplate.
1. Create a Simple Model¶
Create src/app/models/item.py:
from sqlalchemy import String from sqlalchemy.orm import Mapped, mapped_column from app.core.db.database import Base class Item(Base): __tablename__ = "items" id: Mapped[int] = mapped_column("id", autoincrement=True, nullable=False, unique=True, primary_key=True, init=False) name: Mapped[str] = mapped_column(String(100)) description: Mapped[str] = mapped_column(String(500), default="") 2. Create Pydantic Schemas¶
Create src/app/schemas/item.py:
from pydantic import BaseModel, Field class ItemBase(BaseModel): name: str = Field(..., min_length=1, max_length=100) description: str = Field("", max_length=500) class ItemCreate(ItemBase): pass class ItemCreateInternal(ItemCreate): pass class ItemRead(ItemBase): id: int class ItemUpdate(BaseModel): name: str | None = None description: str | None = None class ItemUpdateInternal(ItemUpdate): pass class ItemDelete(BaseModel): is_deleted: bool = True 3. Create CRUD Operations¶
Create src/app/crud/crud_items.py:
from fastcrud import FastCRUD from app.models.item import Item from app.schemas.item import ItemCreateInternal, ItemUpdate, ItemUpdateInternal, ItemDelete CRUDItem = FastCRUD[Item, ItemCreateInternal, ItemUpdate, ItemUpdateInternal, ItemDelete] crud_items = CRUDItem(Item) 4. Create API Endpoints¶
Create src/app/api/v1/items.py:
from typing import Annotated from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.ext.asyncio import AsyncSession from app.api.dependencies import get_current_user from app.core.db.database import async_get_db from app.crud.crud_items import crud_items from app.schemas.item import ItemCreate, ItemRead, ItemUpdate from app.schemas.user import UserRead router = APIRouter(tags=["items"]) @router.post("/", response_model=ItemRead, status_code=201) async def create_item( item: ItemCreate, db: Annotated[AsyncSession, Depends(async_get_db)], current_user: Annotated[UserRead, Depends(get_current_user)] ): """Create a new item.""" db_item = await crud_items.create(db=db, object=item) return db_item @router.get("/{item_id}", response_model=ItemRead) async def get_item( item_id: int, db: Annotated[AsyncSession, Depends(async_get_db)] ): """Get an item by ID.""" db_item = await crud_items.get(db=db, id=item_id) if not db_item: raise HTTPException(status_code=404, detail="Item not found") return db_item @router.get("/", response_model=list[ItemRead]) async def get_items( db: Annotated[AsyncSession, Depends(async_get_db)], skip: int = 0, limit: int = 100 ): """Get all items.""" items = await crud_items.get_multi(db=db, offset=skip, limit=limit) return items["data"] @router.patch("/{item_id}", response_model=ItemRead) async def update_item( item_id: int, item_update: ItemUpdate, db: Annotated[AsyncSession, Depends(async_get_db)], current_user: Annotated[UserRead, Depends(get_current_user)] ): """Update an item.""" db_item = await crud_items.get(db=db, id=item_id) if not db_item: raise HTTPException(status_code=404, detail="Item not found") updated_item = await crud_items.update(db=db, object=item_update, id=item_id) return updated_item @router.delete("/{item_id}") async def delete_item( item_id: int, db: Annotated[AsyncSession, Depends(async_get_db)], current_user: Annotated[UserRead, Depends(get_current_user)] ): """Delete an item.""" db_item = await crud_items.get(db=db, id=item_id) if not db_item: raise HTTPException(status_code=404, detail="Item not found") await crud_items.delete(db=db, id=item_id) return {"message": "Item deleted successfully"} 5. Register the Router¶
Add your new router to src/app/api/v1/__init__.py:
from fastapi import APIRouter from app.api.v1.login import router as login_router from app.api.v1.logout import router as logout_router from app.api.v1.posts import router as posts_router from app.api.v1.rate_limits import router as rate_limits_router from app.api.v1.tasks import router as tasks_router from app.api.v1.tiers import router as tiers_router from app.api.v1.users import router as users_router from app.api.v1.items import router as items_router # Add this line router = APIRouter(prefix="/v1") router.include_router(login_router, prefix="/login") router.include_router(logout_router, prefix="/logout") router.include_router(users_router, prefix="/users") router.include_router(posts_router, prefix="/posts") router.include_router(tasks_router, prefix="/tasks") router.include_router(tiers_router, prefix="/tiers") router.include_router(rate_limits_router, prefix="/rate_limits") router.include_router(items_router, prefix="/items") # Add this line 6. Create and Run Migration¶
Import your new model in src/app/models/__init__.py:
from .user import User from .post import Post from .tier import Tier from .rate_limit import RateLimit from .item import Item # Add this line Create and run the migration:
# For Docker Compose docker compose exec web alembic revision --autogenerate -m "Add items table" docker compose exec web alembic upgrade head # For manual installation cd src uv run alembic revision --autogenerate -m "Add items table" uv run alembic upgrade head 7. Test Your New Endpoint¶
Restart your application and test the new endpoints:
# Create an item curl -X POST "http://localhost:8000/api/v1/items/" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN_HERE" \ -d '{ "name": "My First Item", "description": "This is a test item" }' # Get all items curl -X GET "http://localhost:8000/api/v1/items/" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN_HERE" Debugging Common Issues¶
Logs and Monitoring¶
Check Application Logs¶
Check Database Logs¶
Check Worker Logs¶
Performance Testing¶
Test API Response Times¶
# Test endpoint performance curl -w "Time: %{time_total}s\n" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN_HERE" \ http://localhost:8000/api/v1/users/me Test Database Performance¶
# Check active connections docker compose exec db psql -U postgres -d myapp -c "SELECT count(*) FROM pg_stat_activity;" Monitoring Dashboard¶
Redis Monitor¶
Database Activity¶
# Check database activity docker compose exec db psql -U postgres -d myapp -c "SELECT * FROM pg_stat_activity;" Next Steps¶
Now that you've verified everything works and created your first custom endpoint, you're ready to dive deeper:
Essential Learning¶
- Project Structure - Understand how the code is organized
- Database Guide - Learn about models, schemas, and CRUD operations
- Authentication - Deep dive into JWT and user management
Advanced Features¶
- Caching - Speed up your API with Redis caching
- Background Tasks - Process long-running tasks asynchronously
- Rate Limiting - Protect your API from abuse
Development Workflow¶
- Development Guide - Best practices for extending the boilerplate
- Testing - Write tests for your new features
- Production - Deploy your API to production
Getting Help¶
If you encounter any issues:
- Check the logs for error messages
- Verify your configuration in the
.envfile - Review the GitHub Issues for common solutions
- Search existing issues on GitHub
- Create a new issue with detailed information
Congratulations!¶
You've successfully:
- Verified your FastAPI Boilerplate installation
- Tested core API functionality
- Created your first custom endpoint
- Run database migrations
- Tested authentication and CRUD operations
You're now ready to build amazing APIs with FastAPI!