Skip to main content

Alembic migrations

If you manage schema with Alembic, fastapi-rls adds operation directives so RLS becomes part of your normal migration history — reviewable, reversible, and ordered against your table changes.

Register the directives

Import the module once (anywhere Alembic loads, e.g. your migration env.py or the migration itself). The import has the side effect of registering the op.* directives:

import fastapi_rls.alembic_ops # noqa: F401 — registers op.enable_rls / op.create_policy / …

Available operations

DirectiveEmits
op.enable_rls(table)ALTER TABLE … ENABLE ROW LEVEL SECURITY
op.disable_rls(table)ALTER TABLE … DISABLE ROW LEVEL SECURITY
op.force_rls(table)ALTER TABLE … FORCE ROW LEVEL SECURITY
op.no_force_rls(table)ALTER TABLE … NO FORCE ROW LEVEL SECURITY
op.create_policy(policy)CREATE POLICY … for a bound policy
op.drop_policy(table, name)DROP POLICY IF EXISTS … ON …

A migration

Policies passed to op.create_policy must be bound — pass table= explicitly, since there's no model mixin in a migration:

from alembic import op
from fastapi_rls import TenantPolicy
import fastapi_rls.alembic_ops # noqa: F401


def upgrade():
op.enable_rls("documents")
op.force_rls("documents")
op.create_policy(
TenantPolicy("tenant_isolation", column="tenant_id", table="documents")
)


def downgrade():
op.drop_policy("documents", "tenant_isolation")
op.no_force_rls("documents")
op.disable_rls("documents")
Enable and force

ENABLE ROW LEVEL SECURITY alone leaves the table owner unconstrained. Follow it with op.force_rls(table) so migrations and owner connections are constrained too. See the security model.

Alembic vs the CLI vs the facade

All three drive the same DDL builders; pick the one that fits your workflow:

  • Alembic — RLS changes ride your existing migration history.
  • CLI (fastapi-rls sync) — reconcile a registry against the live database without a migration tool.
  • Facade (rls.sync()) — reconcile from application code at startup.

Alembic gives you explicit, ordered, reversible steps; the CLI/facade give you declarative reconciliation from your policy registry. Many projects use Alembic for the enable/force and the CLI audit in CI to catch drift.