Metaxy + SQLAlchemy¶
Metaxy provides helpers for integrating with SQLAlchemy.
These helpers allow to construct sqlalchemy.MetaData objects for user-defined feature tables and for Metaxy system tables.
This integration is convenient for setting up Alembic migrations.
SQLModel Features
Check out our SQLModel integration for metaclass features that combine Metaxy features with SQLModel ORM models. This is the recommended way to use Metaxy with SQLAlchemy.
Alembic Integration¶
Alembic is a database migration toolkit for SQLAlchemy.
The two helper functions: filter_feature_sqla_metadata and get_system_slqa_metadata can be used to retrieve an SQLAlchemy URL and MetaData object for a given IbisMetadataStore.
filter_feature_sqla_metadata returns table metadata for the user-defined tables, while get_system_slqa_metadata returns metadata for Metaxy's system tables.
Call init_metaxy first
You must call init_metaxy before using filter_feature_sqla_metadata to ensure all features are loaded into the feature graph.
Here is an example Alembic env.py that uses the Metaxy SQLAlchemy integration:
from alembic import context
from metaxy import init_metaxy
from metaxy.ext.sqlalchemy import filter_feature_sqla_metadata
# Alembic Config object
config = context.config
metaxy_cfg = init_metaxy()
store = metaxy_cfg.get_store("my_store")
# import your SQLAlchemy metadata from somewhere
my_metadata = ...
url, target_metadata = filter_feature_sqla_metadata(my_metadata, store)
# Configure Alembic
config.set_main_option("sqlalchemy.url", url)
# continue with the standard Alembic workflow
Multi-Store Setup¶
You can configure separate metadata stores for different environments:
[stores.dev]
type = "metaxy.metadata_store.duckdb.DuckDBMetadataStore"
config = { database = "dev_metadata.duckdb" }
[stores.prod]
type = "metaxy.metadata_store.duckdb.DuckDBMetadataStore"
config = { database = "prod_metadata.duckdb" }
Then create multiple Alembic directories and register them with Alembic:
Separate Alembic Version Tables
When using multiple Alembic environments (e.g., system tables vs feature tables), configure separate version tables to avoid conflicts. Set up separate script locations in alembic.ini:
[dev:metaxy_system]
script_location = alembic/dev/system
[dev:metaxy_features]
script_location = alembic/dev/features
Then pass version_table to context.configure() in each env.py:
context.configure(
url=url,
target_metadata=target_metadata,
version_table="alembic_version_metaxy_system",
)
context.configure(
url=url,
target_metadata=target_metadata,
version_table="alembic_version_metaxy_features",
)
Each environment now tracks migrations independently:
alembic_version_metaxy_systemfor system tablesalembic_version_metaxy_featuresfor feature tables
Create and run migrations separately:
The two environments now can be managed independently:
Alembic + SQLModel¶
To add SQLModel into the mix, make sure to use the SQLModel integration and pass sqlmodel.SQLModel.metadata into filter_feature_sqla_metadata.