SQLModel Integration Plan¶
Purpose¶
SQLModel combines Pydantic models with SQLAlchemy table models through standard Python type annotations. That developer experience aligns strongly with ETLantic and its planned FastAPI control plane.
ETLantic should support SQLModel as an optional integration in three places:
- generating or adapting relational table models from
Datacontracts; - implementing typed SQL-backed control-plane providers;
- reducing duplication between FastAPI schemas and persistence models.
SQLModel should not replace ETLantic's domain models, ContractModel, SQLAlchemy Core-based SQL execution, or provider protocols.
Architectural Boundary¶
ContractModel / ETLantic Data
authoritative logical data contract
│
├── optional generation or adaptation
▼
SQLModel table model
relational application representation
ETLantic provider protocols
│
├── optional reference implementation
▼
SQLModel-backed persistence
ETLantic SQL execution plugin
│
▼
SQLAlchemy Core / dialect
The three layers remain distinct:
Datadefines contractual meaning;- SQLModel may define a convenient relational Python representation;
- SQL execution plugins compile and execute portable SQL intent.
Goals¶
The integration should:
- accept existing SQLModel table models as relational schema sources;
- generate draft SQLModel models from compatible
Datacontracts; - compare SQLModel metadata with declared contracts and observed database schemas;
- provide typed reference stores for registries, runs, reports, events, schema observations, reliability evidence, approvals, and incremental state;
- share appropriate Pydantic schemas with
etlantic-fastapi; - preserve editor completion and static typing;
- use explicit migrations and transactional repositories;
- remain optional and replaceable.
Non-Goals¶
ETLantic will not:
- make SQLModel a core dependency;
- require users to model warehouse tables as ORM entities;
- treat a SQLModel table as the authoritative data contract automatically;
- use ORM relationships to define pipeline lineage or dependencies;
- expose SQLModel sessions from public core APIs;
- use
SQLModel.metadata.create_all()as a production migration strategy; - replace SQLAlchemy Core expressions in SQL transformation implementations;
- infer unrestricted database access from the presence of a table model;
- serialize live ORM objects into plans, reports, or contracts.
Package Shape¶
A separate integration package is preferred:
etlantic-sqlmodel
├── contract adapters
├── model generation
├── metadata inspection
├── repository helpers
├── reference providers
├── FastAPI dependencies
└── conformance tests
Candidate installation:
The package may depend on SQLModel, ETLantic, an explicitly selected database driver, and Alembic in a migration extra or application dependency.
Contract and Table Model Mapping¶
SQLModel to Data¶
An adapter may inspect a SQLModel table class and produce a draft Data
contract or comparison representation.
Useful metadata includes:
- field names and Python annotations;
- SQL column types;
- nullability;
- primary and foreign keys;
- uniqueness and indexes;
- defaults and generated values;
- length, precision, and scale;
- table and schema identity.
The result must identify information that cannot be represented reliably or requires human review.
Data to SQLModel¶
Generation should create reviewable Python source rather than hidden dynamic classes for production use.
from etlantic_sqlmodel import generate_model
result = generate_model(
Customer,
table_name="customer",
primary_key=("customer_id",),
)
Generation must require explicit relational choices that a data contract alone cannot safely determine:
- table and schema name;
- primary and foreign keys;
- identity and sequence behavior;
- indexes and uniqueness;
- database-specific types;
- relationships;
- persistence defaults;
- cascade and deletion behavior.
Generated source should include provenance and be safe to edit normally.
Multiple representations¶
The integration should encourage separate models when write, database, and public API shapes differ:
Customer contract
CustomerRow table model
CustomerCreate request model
CustomerPublic response model
Shared inheritance may reduce duplication, but security-sensitive or database-only fields must not leak into public API schemas.
Control-Plane Persistence¶
SQLModel is a good candidate for reference implementations of ETLantic's provider protocols:
- pipeline and contract registry;
- run and report store;
- lifecycle event store;
- schema observation and acknowledgement history;
- freshness, reconciliation, quality, and statistical evidence history;
- profile and environment revision history;
- policy decision and approval records;
- incremental state and checkpoint store;
- idempotency and submission records.
Public code should depend on provider protocols, not SQLModel repositories. The optional package may implement those protocols using SQLModel sessions and transactions.
FastAPI Integration¶
etlantic-fastapi may offer an optional SQLModel persistence bundle:
from etlantic_fastapi import ETLanticAPI
from etlantic_sqlmodel import SQLModelControlPlane
control_plane = SQLModelControlPlane.from_url(database_url)
api = ETLanticAPI(
registry=control_plane.registry,
run_store=control_plane.runs,
report_store=control_plane.reports,
event_store=control_plane.events,
)
FastAPI dependencies may provide request-scoped sessions to integration repositories. Those sessions must not become pipeline runtime resources or be passed to transformations.
Request, persistence, and response models should remain separate where their security or lifecycle differs.
SQL Execution Integration¶
SQLModel table models may be accepted as convenient relation descriptors:
The adapter should translate table metadata into ETLantic's SQL relation and binding models. The SQL plugin continues to use SQLAlchemy Core and dialect capabilities for query construction, transactions, execution, compilation, write intents, inspection, and reconciliation.
ORM instance loading must not be the default mechanism for bulk ETL.
Migrations and Schema Evolution¶
SQLModel metadata describes a desired relational model but does not replace a migration system.
The integration should:
- generate migration proposals or metadata suitable for Alembic;
- compare contract, SQLModel, observed database, and migration-head schemas;
- integrate differences with schema drift and compatibility analysis;
- require review for destructive or lossy changes;
- record migration revision and database schema fingerprint in plans and reports;
- prevent automatic production
create_all()behavior.
Each mismatch has different meaning and remediation.
Developer Experience¶
The integration should provide:
- completion and type checking for generated models;
- navigation between a
Datacontract and SQLModel table; - contract-versus-table diagnostics;
- safe quick fixes for deterministic field mappings;
- generated model previews;
- migration impact previews;
- FastAPI schema-exposure checks;
- warnings when table fields could leak through API responses;
- CodeLens actions for generate, compare, inspect, and propose migration.
Notebook display may show bounded model and metadata comparisons without opening a database connection implicitly.
Security¶
SQLModel does not create a security boundary.
The integration must:
- use parameterized SQL and approved engines;
- keep database URLs and credentials in secret providers;
- separate control-plane and pipeline-data credentials;
- enforce tenant and workspace filters in repositories;
- prevent mass assignment of protected fields;
- distinguish request, persistence, and response models;
- bound queries, pagination, eager loading, and relationship traversal;
- avoid returning ORM objects directly from generic APIs;
- prohibit automatic schema creation or destructive migration in production;
- audit migrations, approvals, state changes, and administrative writes;
- avoid embedding session, engine, metadata, or ORM state in serialized ETLantic models.
Testing¶
The integration conformance suite should cover:
- SQLModel and
Datatype mapping; - nullability, defaults, precision, keys, indexes, and relationships;
- unsupported and lossy mappings;
- deterministic source generation;
- contract, model, migration, and observed-schema comparisons;
- sync and async repository behavior where supported;
- transaction rollback and concurrent updates;
- tenant isolation and pagination;
- idempotent run submission and state transitions;
- FastAPI request and response field separation;
- migration safety and production
create_all()prohibition; - compatibility with supported SQLModel, Pydantic, SQLAlchemy, and Python versions.
Roadmap Placement¶
| Release | SQLModel capability |
|---|---|
| 0.3 | Adapter and mapping protocols, source-generation design |
| 0.6 | SQLModel relation descriptors accepted by SQL plugins |
| 0.9 | Optional package scaffold, generator CLI, conformance suite |
| 1.1 | FastAPI control-plane persistence bundle |
| 1.2 | SQLModel-backed registry and history reference providers |
| 1.3 | SQLModel-backed state and idempotency reference providers |
| 1.5 | IDE generation, navigation, comparison, and migration actions |
| Later 1.x | Mature Alembic integration and provider templates |
Decision¶
ETLantic should incorporate SQLModel as:
An optional typed bridge between contracts, relational application models, FastAPI schemas, and reference persistence providers.
It should not become:
The pipeline model, the data contract model, or the SQL execution engine.