fastapi/sqlmodel

SQL databases in Python, designed for simplicity, compatibility, and robustness.

17,842 stars Python 7 components

Bridges Pydantic models and SQLAlchemy tables into unified Python classes

Data enters as Python class definitions with type annotations and Field() declarations. SQLModel's metaclass processes these to generate both Pydantic validation schemas and SQLAlchemy table schemas. At runtime, data flows through Pydantic validation for incoming requests, gets stored via SQLAlchemy sessions, and serializes back through Pydantic for outgoing responses.

Under the hood, the system uses 2 feedback loops, 3 data pools, 3 control points to manage its runtime behavior.

A 7-component library. 317 files analyzed. Data flows through 7 distinct pipeline stages.

How Data Flows Through the System

Data enters as Python class definitions with type annotations and Field() declarations. SQLModel's metaclass processes these to generate both Pydantic validation schemas and SQLAlchemy table schemas. At runtime, data flows through Pydantic validation for incoming requests, gets stored via SQLAlchemy sessions, and serializes back through Pydantic for outgoing responses.

  1. Model Definition — Developer defines a class inheriting from SQLModel with type-annotated fields and table=True parameter. The SQLModelMetaclass intercepts this class creation to build dual Pydantic/SQLAlchemy schemas.
  2. Field Processing — Field() functions are called during class definition, creating FieldInfo objects that contain both Pydantic validation rules and SQLAlchemy column specifications like indexes, foreign keys, and constraints.
  3. Table Creation — create_db_and_tables() calls SQLModel.metadata.create_all(engine) to generate actual database tables from the collected SQLAlchemy table metadata of all registered SQLModel classes. [SQLModel]
  4. Request Validation — Incoming data (typically JSON from HTTP requests) gets parsed and validated through Pydantic's validation pipeline using the model's type annotations and Field constraints.
  5. Database Persistence — Validated model instances are added to SQLAlchemy sessions using session.add(), then persisted to the database with session.commit(), with session.refresh() updating the instance with generated database values like auto-increment IDs. [Hero → Hero]
  6. Query Execution — Database queries use the type-safe select() function to build SQLAlchemy queries, executed via session.exec() which returns properly typed result objects that maintain both database and Pydantic model capabilities.
  7. Response Serialization — Retrieved database objects are automatically serialized to JSON through Pydantic's serialization, often using dedicated response models like HeroPublic to control which fields are exposed in the API. [Hero → HeroPublic]

Data Models

The data structures that flow between stages — the contracts that hold the system together.

SQLModel sqlmodel/main.py
Base class combining Pydantic BaseModel with SQLAlchemy DeclarativeMeta, containing model_config: SQLModelConfig, metadata: ClassVar[MetaData], and registry: ClassVar[registry]
Defined with table=True/False parameter, validated through Pydantic, persisted via SQLAlchemy sessions, serialized to JSON for APIs
Hero docs_src/tutorial/fastapi/app_testing/tutorial001_py310/main.py
SQLModel with id: int | None = Field(primary_key=True), name: str = Field(index=True), secret_name: str, age: int | None = Field(index=True)
Created from HTTP JSON, validated by Pydantic, stored in database via SQLAlchemy session, returned as validated response model
HeroCreate docs_src/tutorial/fastapi/app_testing/tutorial001_py310/main.py
Pydantic-only model inheriting from HeroBase without id field, used for input validation
Deserializes from HTTP request JSON, validates fields, converts to Hero instance for database operations
HeroPublic docs_src/tutorial/fastapi/app_testing/tutorial001_py310/main.py
Pydantic-only model inheriting from HeroBase with required id: int field for API responses
Populated from database Hero instances, serialized to JSON for API responses with guaranteed id field
FieldInfo sqlmodel/main.py
Dataclass with foreign_key: Any = Undefined, containing SQLAlchemy-specific field metadata extensions
Created by Field() function calls, processed during class creation to generate SQLAlchemy Column objects

Hidden Assumptions

Things this code relies on but never validates. These are the things that cause silent failures when the system changes.

critical Resource unguarded

The database connection pool has sufficient connections available for all concurrent FastAPI requests, with no connection timeout or deadlock handling

If this fails: Under high concurrent load, requests will hang indefinitely waiting for database connections, causing the FastAPI app to become unresponsive without any error indication

docs_src/tutorial/fastapi/app_testing/tutorial001_py310/main.py:get_session
critical Ordering unguarded

session.refresh(hero_deadpond) assumes the database transaction has fully committed and the row is visible for re-reading, but refresh() is called immediately after commit() without verifying transaction completion

If this fails: In databases with read-after-write consistency issues or replication lag, refresh() might read stale data or fail to find the just-inserted row, causing silent data inconsistencies

docs_src/tutorial/code_structure/tutorial001_py310/app.py:create_heroes
critical Contract unguarded

Hero.model_validate(hero) assumes the HeroCreate instance contains exactly the fields that Hero expects, but doesn't verify field compatibility or handle missing required fields that might exist in Hero but not HeroCreate

If this fails: If Hero has required fields not in HeroCreate, or if field types have diverged between models, model_validate() will raise a ValidationError that crashes the API endpoint instead of returning a proper HTTP error response

docs_src/tutorial/fastapi/app_testing/tutorial001_py310/main.py:create_hero
critical Environment unguarded

The SQLite database file 'database.db' is writable in the current working directory and the process has filesystem permissions to create, read, and write the file

If this fails: In containerized environments or restricted filesystems, the engine creation or table creation will fail with cryptic SQLite errors, causing the entire application startup to crash

docs_src/tutorial/code_structure/tutorial001_py310/database.py:create_engine
critical Temporal unguarded

The metaclass processes SQLModel classes in an order where all referenced foreign key targets have already been defined and registered in SQLModel.metadata

If this fails: If models with foreign key relationships are defined before their target tables, SQLAlchemy will create invalid foreign key constraints or fail with 'table not found' errors during metadata.create_all()

sqlmodel/main.py:SQLModelMetaclass
warning Scale weakly guarded

The limit parameter is capped at 100 via Query(default=100, le=100), but assumes this is sufficient for all use cases and that offset-based pagination won't cause performance issues on large datasets

If this fails: Large offset values (e.g., offset=1000000) will cause extremely slow database queries as SQLite must scan and skip all preceding rows, potentially causing request timeouts

docs_src/tutorial/fastapi/app_testing/tutorial001_py310/main.py:read_heroes
warning Shape unguarded

The session.add(db_hero) followed by session.commit() assumes the db_hero instance doesn't contain circular references or cascading relationships that could cause infinite recursion during serialization

If this fails: If Hero has complex relationships that create cycles, the final return statement will fail with RecursionError when FastAPI tries to serialize the response to JSON

docs_src/tutorial/fastapi/app_testing/tutorial001_py310/main.py:create_hero
warning Domain weakly guarded

The connect_args={'check_same_thread': False} setting assumes the application will properly handle SQLite's thread safety by ensuring no concurrent access to the same session from multiple threads

If this fails: Multiple FastAPI worker threads using the same SQLite connection could corrupt database state or cause undefined behavior, since SQLite connections aren't actually thread-safe despite disabling the check

docs_src/tutorial/fastapi/app_testing/tutorial001_py310/main.py:sqlite_url
warning Resource unguarded

SQLModel.metadata.create_all(engine) assumes the database schema migration can complete without conflicts, and that all registered SQLModel classes are finalized and won't be modified after this call

If this fails: If called multiple times or if model definitions change after tables are created, create_all() might silently fail to update schema or create duplicate/conflicting constraints

docs_src/tutorial/code_structure/tutorial001_py310/database.py:create_db_and_tables
warning Contract weakly guarded

HeroUpdate allows all fields to be None, assuming partial updates are always valid, but doesn't validate business rules like 'age cannot be negative' or 'name cannot be empty string'

If this fails: Clients can send updates that set required fields to None or invalid values, potentially corrupting data or violating business constraints that aren't enforced at the database level

docs_src/tutorial/fastapi/app_testing/tutorial001_py310/main.py:HeroUpdate

System Behavior

How the system operates at runtime — where data accumulates, what loops, what waits, and what controls what.

Data Pools

SQLModel.metadata (registry)
Global MetaData registry that accumulates table definitions from all SQLModel classes marked with table=True, used by create_all() for schema generation
Database Engine (database)
SQLAlchemy engine connection pool that manages database connections and transaction state across session operations
Session Context (state-store)
SQLAlchemy session that tracks object changes and manages transaction boundaries within context manager scopes

Feedback Loops

Delays

Control Points

Technology Stack

Pydantic (framework)
Data validation and serialization engine that handles JSON parsing, type validation, and API response formatting for SQLModel classes
SQLAlchemy (database)
ORM and database abstraction layer that generates SQL, manages connections, and provides session-based transaction handling
FastAPI (framework)
Web framework integration target that consumes SQLModel classes for automatic API documentation and request/response handling
typing-extensions (library)
Provides advanced type annotation features needed for complex field definitions and cross-version compatibility
pytest (testing)
Test framework running comprehensive test suites for model behavior, database operations, and FastAPI integration

Key Components

Explore the interactive analysis

See the full architecture map, data flow, and code patterns visualization.

Analyze on CodeSea

Related Library Repositories

Frequently Asked Questions

What is sqlmodel used for?

Bridges Pydantic models and SQLAlchemy tables into unified Python classes fastapi/sqlmodel is a 7-component library written in Python. Data flows through 7 distinct pipeline stages. The codebase contains 317 files.

How is sqlmodel architected?

sqlmodel is organized into 4 architecture layers: Core Model Layer, SQL Extensions, Compatibility Layer, Documentation Examples. Data flows through 7 distinct pipeline stages. This layered structure keeps concerns separated and modules independent.

How does data flow through sqlmodel?

Data moves through 7 stages: Model Definition → Field Processing → Table Creation → Request Validation → Database Persistence → .... Data enters as Python class definitions with type annotations and Field() declarations. SQLModel's metaclass processes these to generate both Pydantic validation schemas and SQLAlchemy table schemas. At runtime, data flows through Pydantic validation for incoming requests, gets stored via SQLAlchemy sessions, and serializes back through Pydantic for outgoing responses. This pipeline design reflects a complex multi-stage processing system.

What technologies does sqlmodel use?

The core stack includes Pydantic (Data validation and serialization engine that handles JSON parsing, type validation, and API response formatting for SQLModel classes), SQLAlchemy (ORM and database abstraction layer that generates SQL, manages connections, and provides session-based transaction handling), FastAPI (Web framework integration target that consumes SQLModel classes for automatic API documentation and request/response handling), typing-extensions (Provides advanced type annotation features needed for complex field definitions and cross-version compatibility), pytest (Test framework running comprehensive test suites for model behavior, database operations, and FastAPI integration). A focused set of dependencies that keeps the build manageable.

What system dynamics does sqlmodel have?

sqlmodel exhibits 3 data pools (SQLModel.metadata, Database Engine), 2 feedback loops, 3 control points, 2 delays. The feedback loops handle self-correction and recursive. These runtime behaviors shape how the system responds to load, failures, and configuration changes.

What design patterns does sqlmodel use?

4 design patterns detected: Hybrid Model Pattern, Dependency Injection for Sessions, Model Specialization, Version Compatibility Abstraction.

Analyzed on April 20, 2026 by CodeSea. Written by .