AI
50 AI Prompts for Python FastAPI Development
A developer-tested set of 50 prompts for building production-ready APIs with Python and FastAPI — covering project structure, Pydantic v2 models, authentication, SQLAlchemy, background tasks, testing with pytest, and Docker deployment.
Advertisement
How to Use These FastAPI Prompts Effectively
FastAPI generates well with AI assistance because the framework is explicit — route decorators, Pydantic models, and dependency injection are all clearly structured. The prompts here are written to take advantage of that structure. Each prompt names the exact file being created, the Pydantic models being used, and the dependency injections being applied so the output fits directly into an existing project.
These prompts assume Python 3.12, FastAPI 0.115+, Pydantic v2, SQLAlchemy 2.0 async, and Alembic for migrations. For async database access they use asyncpg with PostgreSQL. The testing prompts use pytest with httpx and pytest-asyncio.
One thing that saves significant time: always define your Pydantic schemas before generating route code. If the AI sees your UserCreate, UserRead, and UserUpdate schemas, the generated route handlers will use them correctly. If it has to guess the schema shape, you spend time correcting field names and types. Paste schemas early.
- Define Pydantic schemas before generating route handlers — the AI will use them directly
- Specify whether you are using sync or async SQLAlchemy — the session dependency differs significantly
- For auth prompts, paste your existing User model so the prompt generates compatible code
- When output uses print() for logging, replace with the loguru or standard logging setup from your project
Project Setup and Structure (Prompts 1–8)
Prompt 1: "Set up a FastAPI project with the following structure: app/main.py (application factory), app/api/v1/router.py (main v1 router), app/core/config.py (settings using pydantic-settings), app/core/database.py (async SQLAlchemy engine and session), app/models/ (SQLAlchemy models), app/schemas/ (Pydantic schemas), app/services/ (business logic), and app/dependencies/ (FastAPI dependencies). Create a pyproject.toml with fastapi, uvicorn[standard], sqlalchemy[asyncio], asyncpg, pydantic-settings, and alembic." — Prompt 2: "Create app/core/config.py using pydantic-settings BaseSettings. Settings: DATABASE_URL (PostgreSQL async URL), SECRET_KEY (min 32 chars), ALGORITHM (default HS256), ACCESS_TOKEN_EXPIRE_MINUTES (default 30), ALLOWED_ORIGINS (list of strings), DEBUG (boolean, default False). Load from a .env file. Export a settings singleton."
Prompt 3: "Create app/core/database.py for async SQLAlchemy. Set up an async engine using create_async_engine with the DATABASE_URL from settings. Create an async session factory using async_sessionmaker. Write a get_db dependency function that yields an AsyncSession and commits on success or rolls back on exception. Export engine, AsyncSessionLocal, and Base." — Prompt 4: "Create app/main.py as the FastAPI application factory. Include the v1 router with prefix /api/v1. Add CORSMiddleware with allowed origins from settings. Add a startup event that checks the database connection. Add a 404 handler that returns { detail: 'Resource not found' }. Add a global exception handler for unhandled errors that logs the traceback and returns 500 in production."
Prompt 5: "Set up structured logging using loguru. In app/core/logging.py, configure loguru to output JSON format in production and human-readable format in development. Add a request logging middleware that logs method, path, status code, and response time for every request. Exclude the /health endpoint from request logging." — Prompt 6: "Create a /api/v1/health endpoint that returns { status: ok, db: connected|disconnected, uptime_seconds: float }. Check the database connection by running SELECT 1. Return 200 if everything is healthy, 503 if the database check fails. This endpoint must not require authentication." — Prompt 7: "Write a custom HTTPException handler and a RequestValidationError handler. The exception handler should return { success: false, detail: exception.detail, status_code: integer }. The validation error handler should format Pydantic v2 validation errors into { success: false, errors: [{ field, message }] } so API clients get consistent error shapes." — Prompt 8: "Create a Makefile with commands for: running the dev server with uvicorn --reload, running database migrations with alembic upgrade head, creating a new migration with alembic revision --autogenerate, running tests with pytest, and running the linter with ruff. Document each command with a comment."
Pydantic Models and Route Handlers (Prompts 9–16)
Prompt 9: "Create Pydantic v2 schemas for a User resource in app/schemas/user.py. UserBase: email (EmailStr), name (str min 2 max 80). UserCreate extends UserBase: password (str min 8). UserUpdate: all fields optional. UserRead extends UserBase: id (int or UUID), created_at (datetime), is_active (bool). Configure UserRead with model_config = ConfigDict(from_attributes=True) for ORM compatibility." — Prompt 10: "Create a SQLAlchemy 2.0 User model in app/models/user.py. Columns: id (Integer primary key), email (String unique not null), name (String not null), hashed_password (String not null), is_active (Boolean default True), is_superuser (Boolean default False), created_at (DateTime default utcnow), updated_at (DateTime onupdate). Use the mapped_column syntax from SQLAlchemy 2.0."
Prompt 11: "Write CRUD routes for the User resource in app/api/v1/users.py. GET /users (paginated, admin only), GET /users/{user_id}, POST /users (admin only), PUT /users/{user_id}, DELETE /users/{user_id} (admin only). Use Depends(get_db) for the session and Depends(get_current_user) for auth. Return UserRead schema from all endpoints. Raise 404 with detail 'User not found' when a user does not exist." — Prompt 12: "Add query parameter support to GET /users. Parameters: skip (int default 0), limit (int default 20 max 100), search (optional str that filters name and email with ILIKE), is_active (optional bool filter). Use SQLAlchemy select() with where() clauses for filtering. Return a response schema with items: list[UserRead], total: int, skip: int, limit: int."
Prompt 13: "Create a user service in app/services/user_service.py with async functions: get_user, get_user_by_email, get_users, create_user, update_user, delete_user. Each function takes an AsyncSession as the first argument. create_user should check for duplicate email before inserting and raise HTTPException 409 if the email exists. Keep all database queries in the service layer — route handlers should not use SQLAlchemy directly." — Prompt 14: "Write a path parameter validator as a FastAPI dependency. Create valid_user_id in app/dependencies/common.py that takes user_id: int as a path parameter, queries the database for the user, and either returns the User ORM object or raises 404. Use it in route handlers with Depends(valid_user_id) to eliminate the repetitive get-or-404 pattern in every route." — Prompt 15: "Add response caching to a GET endpoint using a simple in-memory cache. Cache GET /users/{user_id} responses for 60 seconds using a dictionary keyed by user_id. Invalidate the cache entry on PUT and DELETE for the same user_id. Use a FastAPI middleware or dependency for cache read/write." — Prompt 16: "Create file upload support in FastAPI. Add a POST /users/{user_id}/avatar endpoint that accepts a UploadFile. Validate the content type is image/jpeg or image/png. Validate the file size is under 2MB by reading the file in chunks. Save the file to a local uploads directory with a UUID filename. Return the file URL in the response."
Authentication and Permissions (Prompts 17–23)
Prompt 17: "Implement JWT authentication in FastAPI. In app/core/security.py: write create_access_token(data: dict, expires_delta: timedelta) using python-jose and the SECRET_KEY and ALGORITHM from settings. Write verify_token(token: str) that decodes the JWT and returns the payload or raises 401 on failure. In app/api/v1/auth.py: add POST /auth/login that accepts OAuth2PasswordRequestForm and returns an access token on valid credentials." — Prompt 18: "Create a get_current_user dependency in app/dependencies/auth.py. Use OAuth2PasswordBearer to extract the token from the Authorization header. Call verify_token to decode it. Fetch the user from the database using the sub field (user id) from the token payload. Raise 401 if the token is invalid or the user does not exist. Raise 400 if the user account is inactive."
Prompt 19: "Add a get_current_superuser dependency that calls get_current_user and then checks is_superuser. Raise 403 with detail 'Superuser privileges required' if the check fails. Show how to apply it to admin-only endpoints alongside the regular auth dependency." — Prompt 20: "Implement a refresh token system. On login, issue both a short-lived access token (30 minutes) and a long-lived refresh token (7 days). Store the refresh token hash in a RefreshToken database table tied to the user. Add POST /auth/refresh that accepts the refresh token in the request body, validates it against the database, and issues a new access token. Add POST /auth/logout that deletes the stored refresh token." — Prompt 21: "Add OAuth2 with Google. Use authlib with its Starlette integration. Create GET /auth/google/login that redirects to the Google OAuth flow. Create GET /auth/google/callback that exchanges the code for a token, fetches the user email from the Google userinfo endpoint, finds or creates the user in the database, and returns a JWT. Store a is_oauth_user boolean on the User model."
Prompt 22: "Implement role-based access control. Add a roles column to the User model as an Array of strings (PostgreSQL). Write a require_roles(*roles: str) dependency factory that returns a dependency checking if the current user has any of the required roles. Usage: Depends(require_roles('admin', 'manager')). Raise 403 with a clear message if the role check fails." — Prompt 23: "Add rate limiting to the authentication endpoints using slowapi. Limit POST /auth/login to 10 requests per minute per IP address. Limit POST /auth/register to 5 requests per minute per IP. Apply a general limit of 100 requests per minute per IP to all other routes. Return 429 with a Retry-After header when limits are exceeded."
Background Tasks, Async, and Database Patterns (Prompts 24–35)
Prompt 24: "Use FastAPI BackgroundTasks to send a welcome email after user registration. In the POST /users registration endpoint, add background_tasks: BackgroundTasks as a parameter. After creating the user, call background_tasks.add_task(send_welcome_email, user.email, user.name). The send_welcome_email function should use aiosmtplib to send an async email. This way the HTTP response returns immediately and the email sends in the background." — Prompt 25: "Set up Celery with Redis for longer-running background tasks in FastAPI. Create app/worker.py with a Celery instance. Write a send_email task and a generate_report task. Show how to call celery_app.send_task from within a FastAPI route handler. Add a /tasks/{task_id}/status endpoint that polls the Celery result backend and returns the task state."
Prompt 26: "Write complex SQLAlchemy 2.0 async queries. Show: a query with a JOIN across two tables using selectinload for lazy relationship loading, a query with group by and count using func.count(), and a bulk insert using insert().values() with a list of dicts. Use async with AsyncSession as the session context." — Prompt 27: "Set up Alembic for database migrations with an async FastAPI project. Create an alembic.ini and env.py that work with the async SQLAlchemy engine. Configure env.py to import all model modules so autogenerate detects changes. Show the commands to create the initial migration, apply it, and roll back one version." — Prompt 28: "Implement database connection pooling configuration for production. Configure pool_size=10, max_overflow=20, pool_timeout=30, and pool_pre_ping=True on the async engine. Explain what each parameter controls and what happens when all connections are in use. Add pool event listeners that log when a connection is checked out and returned."
Prompt 29: "Create a generic repository pattern for SQLAlchemy 2.0. Write an AsyncRepository base class in app/repositories/base.py with typed methods: get(id), get_or_404(id), list(skip, limit, **filters), create(schema), update(id, schema), delete(id). Use TypeVar and Generic to make it work with any SQLAlchemy model and Pydantic schema pair. Show a UserRepository that extends it." — Prompt 30: "Add database transaction support across multiple service calls. Write a unit_of_work context manager in app/core/uow.py that starts a transaction, provides a session to the calling code, commits on clean exit, and rolls back on exception. Show how to use it when a route handler needs to write to two tables atomically." — Prompt 31: "Write a data pagination helper. Create a paginate(query, skip: int, limit: int, session: AsyncSession) async function that executes the query twice: once with count() to get the total and once with limit/offset for the page. Return PagedResult with items, total, skip, limit, and helper properties has_next and has_prev."
- Prompt 32: "Create a caching layer using Redis with aioredis. Write a cache dependency that provides get(key) and set(key, value, ttl) methods. Apply it to the GET /users/{user_id} endpoint to cache the response for 60 seconds. Invalidate the cache in the update and delete routes. Show how to serialize and deserialize Pydantic models for Redis storage."
- Prompt 33: "Set up SQLAlchemy event listeners for audit logging. Log every INSERT, UPDATE, and DELETE on selected models to an AuditLog table with the table name, operation, the changed row id, the current user id (from a context variable), and a timestamp. Use SQLAlchemy after_bulk_delete and after_bulk_update session events."
- Prompt 34: "Implement soft delete for SQLAlchemy models. Add deleted_at (nullable DateTime) to a base model mixin. Write a SoftDeleteMixin class and apply it to models that need soft delete. Override the default query in the repository so deleted records are excluded automatically. Add a hard_delete method for permanent removal when needed."
- Prompt 35: "Create a database health check that runs on startup and on the /health endpoint. Check that the connection pool is healthy by running SELECT 1 and verify response time is under 100ms. Log a warning if the pool has fewer than 2 idle connections. Return the pool status (size, checked out, overflow) in the /health response for ops visibility."
Testing With pytest and httpx (Prompts 36–43)
Prompt 36: "Set up async pytest testing for a FastAPI application. Install pytest, pytest-asyncio, httpx, and factory-boy. Create conftest.py with: an async event loop fixture (session scope), a test database URL using a separate test database, an async_client fixture using httpx.AsyncClient with the FastAPI app, and a db fixture that creates all tables before the session and drops them after." — Prompt 37: "Write integration tests for POST /api/v1/auth/login. Test cases: returns 200 and an access token with valid credentials, returns 401 with wrong password, returns 422 if email format is invalid, returns 401 if the user does not exist, returns 400 if the user account is inactive. Create a test user using factory-boy before the test." — Prompt 38: "Write tests for the user CRUD endpoints. Use the async_client fixture. For protected endpoints, create a helper get_auth_headers(user) that logs in and returns the Authorization header. Test: GET /users returns 403 for non-admin, GET /users/{id} returns 404 for unknown id, PUT /users/{id} returns 403 when updating another user without admin rights."
Prompt 39: "Test the background task email sending. Mock the send_welcome_email function using unittest.mock.patch. After calling POST /users to register, verify the mock was called with the correct email and name. Since background tasks run synchronously during testing with the TestClient, the mock should be called before the response returns." — Prompt 40: "Create pytest fixtures using factory-boy for User and Post models. UserFactory should set a random email, a hashed password (use a fixed plain password so tests can log in), and reasonable defaults for all required fields. Show how to create a user, an admin user, and a batch of 10 users with different emails in a single test." — Prompt 41: "Write tests for the JWT authentication middleware. Test: a protected endpoint returns 401 with no Authorization header, returns 401 with a malformed token, returns 401 with an expired token (use a token with a past expiry date), and returns 200 with a valid token. Use freezegun to control time for the expiry test."
Prompt 42: "Test file upload with httpx. Build a test that posts a small valid JPEG file to the avatar upload endpoint. Verify the response includes the file URL. Test that oversized files return 413. Test that non-image files return 422. Use io.BytesIO to create test file content in memory without actual files." — Prompt 43: "Set up test coverage with pytest-cov. Add a pytest.ini or pyproject.toml section that runs coverage automatically, excludes test files and migration files, and requires a minimum coverage of 75%. Configure it to generate both a terminal report and an HTML report. Add a CI step that fails the build if coverage drops below the threshold."
Middleware, Security, and Deployment (Prompts 44–50)
Prompt 44: "Write a request ID middleware for FastAPI. For every incoming request, generate a UUID, add it as X-Request-ID to both the request state and the response headers. Include the request ID in all log messages during that request using a context variable. This makes tracing a specific request through distributed logs much easier." — Prompt 45: "Add input sanitization middleware. Strip leading and trailing whitespace from all string values in the JSON request body recursively. Remove any keys that start with $ to prevent NoSQL-style injection patterns. Apply this transformation before the request reaches the route handler." — Prompt 46: "Configure trusted host middleware and HTTPS redirect for production. Add TrustedHostMiddleware with allowed hosts from the settings. Add HTTPSRedirectMiddleware when DEBUG is False. Add security headers: X-Content-Type-Options: nosniff, X-Frame-Options: DENY, X-XSS-Protection: 1; mode=block. Apply these at the middleware layer so all routes inherit them."
Prompt 47: "Write a graceful shutdown handler for the FastAPI application. On SIGTERM, stop accepting new requests, wait for in-flight requests to complete (up to 30 seconds), close all database connections, and exit cleanly. Use the lifespan context manager introduced in FastAPI 0.95+ instead of the deprecated on_event decorators." — Prompt 48: "Create a Dockerfile for the FastAPI application. Multi-stage build: stage 1 installs dependencies with pip into a virtual environment. Stage 2 copies only the venv and application code. Use python:3.12-slim as the base. Run as a non-root user. Start with uvicorn using the number of workers set by the WEB_CONCURRENCY environment variable (default 1). Expose port 8000." — Prompt 49: "Write a docker-compose.yml for local development. Services: api (FastAPI app with volume mount for hot reload using uvicorn --reload), db (postgres:16 with a named volume, POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB from a .env file), redis (redis:7-alpine for caching and Celery broker), and worker (same image as api but running the Celery worker command)." — Prompt 50: "Create a production deployment checklist for FastAPI on a Ubuntu server with nginx. Cover: configuring nginx as a reverse proxy to uvicorn, setting up a systemd service file that restarts uvicorn on failure, running alembic upgrade head before starting the new version, environment variable management with a .env file owned by the service user (not world-readable), and setting up a basic health check cron that alerts if /health returns non-200."
FAQ
Is FastAPI good for production use?
Yes. FastAPI is used in production by a significant number of companies and handles high concurrency well due to its async-first design. The main things to get right in production are connection pool sizing, worker count tuned to your server CPU count, and proper exception handling so unhandled errors do not silently return 500s.
Should I use sync or async SQLAlchemy with FastAPI?
Async SQLAlchemy is the right choice for FastAPI because it does not block the event loop during database operations. The setup is slightly more complex than sync, but the performance benefit under load is significant. If your team is new to async Python, start with sync and migrate — the patterns are almost identical.
Pydantic v1 or v2 for new FastAPI projects?
Pydantic v2 for all new projects. It is significantly faster, has better TypeScript-style validation, and is now the default in current FastAPI versions. The syntax changed from v1 — the most common adjustment is using model_config = ConfigDict(...) instead of the inner Config class.
How do these prompts work with async databases other than PostgreSQL?
The SQLAlchemy prompts work with any database that has an async driver. For MySQL use aiomysql, for SQLite use aiosqlite. Swap the driver in the DATABASE_URL and the rest of the SQLAlchemy patterns stay the same. For MongoDB, replace the SQLAlchemy prompts with Motor (the async MongoDB driver) — the route and schema prompts stay applicable.
Can I use these prompts with Django REST Framework instead of FastAPI?
The auth, validation, and deployment prompts partially adapt to DRF. But DRF uses class-based views, serializers instead of Pydantic, and Django ORM instead of SQLAlchemy — most structural prompts would need rewriting for DRF. These prompts are FastAPI-specific.
Related free tools
If you want to turn this topic into action, use one of ShortIQ's free tools for campaign planning, UTM structure, or QR distribution.
Continue Reading
Explore more guides on link shortener SaaS strategy, Bitly alternatives, and white label link management.
Was this article helpful?
Tell us if this guide solved the problem or what was still missing. We use this to improve the blog and only follow up if you explicitly allow it.