Skip to main content

terminusdb-migrations

PyPI Python

Schema diff and migration planning for TerminusDB, using Pydantic models as the desired schema.

terminusdb-migrations compares the live TerminusDB schema with schema documents generated from Python models and produces a migration plan that can be reviewed, dry-run, and applied through the native TerminusDB Migration API.

Pydantic models
      ↓
desired TerminusDB schema
      ↓
       diff  ← current TerminusDB schema
      ↓
migration plan
      ↓
native TerminusDB Migration API

It is designed to work with terminusdb-pydantic and terminusdb-async.

Status: early-stage / pre-1.0. Inspect generated migration plans before applying them to production data.

Project status: this is a community package and is not an official TerminusDB migration tool.

Installation

With uv:

uv add terminusdb-migrations

With pip:

python -m pip install terminusdb-migrations

Python 3.11+ is supported.

Internal package dependencies intentionally stay broad across patch releases:

terminusdb-async    >=0.1.0,<1.0.0
terminusdb-pydantic >=0.1.0,<1.0.0

The minimum compatible version is only raised when a release actually requires newer API.

Quick start

Define the desired schema as Pydantic models:

from terminusdb_pydantic import LexicalKey, TerminusModel


class Discipline(TerminusModel):
    __terminus_key__ = LexicalKey("code")

    code: str
    name: str
    description: str | None = None


MODELS = [Discipline]

Build a migration plan against the live TerminusDB schema:

from terminusdb_async import AsyncTerminusClient
from terminusdb_migrations import MigrationManager


async def inspect_schema() -> None:
    async with AsyncTerminusClient(
        "http://localhost:6363",
        organization="admin",
        database="edtech",
        username="admin",
        password="root",
    ) as db:
        manager = MigrationManager(db, MODELS)
        plan = await manager.plan()

        print(plan.render())

Apply the reviewed plan:

await manager.apply(
    plan,
    author="schema-bot",
    message="Synchronize schema",
)

Dry run

Use TerminusDB's migration dry-run before applying generated operations:

await manager.apply(
    plan,
    author="schema-bot",
    message="Check schema synchronization",
    dry_run=True,
)

If a plan is marked destructive, allow_destructive=True is still required before it can be sent to TerminusDB. Destructive plans must be acknowledged explicitly.

What the planner does

The current planner is intentionally conservative.

Schema difference Planner behavior
New class CreateClass
New enum schema document insert
New optional property CreateClassProperty
New required property warning; no default is invented
Existing property type changed CastClassProperty
Enum value added ExpandEnum
Enum value removed warning + destructive
Key changed ChangeKey + destructive
Property removed from model warning + destructive
Class or enum absent from models warning + destructive

This table describes the current 0.1.x behavior.

MigrationPlan

A generated plan exposes:

plan.operations
plan.schema_documents
plan.warnings
plan.destructive
plan.empty

For human review:

print(plan.render())

operations

Native TerminusDB migration operations ready for the Migration API.

schema_documents

Schema documents that need to be inserted outside the migration operation list. In the current implementation, a newly introduced enum is handled this way.

warnings

Changes that the planner refuses to guess automatically.

destructive

Signals that applying the plan may remove information or materially change identity semantics.

Safety model

Automatic schema diff cannot always infer developer intent.

For example, these two schemas are ambiguous:

class Discipline(TerminusModel):
    title: str

and:

class Discipline(TerminusModel):
    name: str

The difference may mean either:

  • rename title to name; or
  • delete title and add an unrelated name.

The planner therefore prefers warnings over silently destructive guesses.

The same principle applies to required properties without defaults, enum contractions, removals, and key changes.

CLI

The package installs the tdb-migrate command.

Expose a model registry from a Python module:

# app/models.py

from terminusdb_pydantic import LexicalKey, TerminusModel


class Discipline(TerminusModel):
    __terminus_key__ = LexicalKey("code")

    code: str
    name: str


MODELS = [Discipline]

Inspect changes:

tdb-migrate plan \
  --models app.models:MODELS \
  --db edtech

Dry-run the migration:

tdb-migrate apply \
  --models app.models:MODELS \
  --db edtech \
  --author schema-bot \
  --message "Synchronize schema" \
  --dry-run

Apply after review:

tdb-migrate apply \
  --models app.models:MODELS \
  --db edtech \
  --author schema-bot \
  --message "Synchronize schema"

For a plan explicitly marked destructive:

tdb-migrate apply \
  --models app.models:MODELS \
  --db edtech \
  --author schema-bot \
  --message "Apply reviewed destructive migration" \
  --allow-destructive

Configuration

The CLI accepts command-line arguments and environment variables for the TerminusDB connection.

Useful environment variables:

TERMINUSDB_URL
TERMINUSDB_ORG
TERMINUSDB_USER
TERMINUSDB_PASSWORD
TERMINUSDB_TOKEN

Example:

export TERMINUSDB_URL=http://localhost:6363
export TERMINUSDB_ORG=admin
export TERMINUSDB_USER=admin
export TERMINUSDB_PASSWORD=root

tdb-migrate plan --models app.models:MODELS --db edtech

End-to-end example

from terminusdb_async import AsyncTerminusClient
from terminusdb_migrations import MigrationManager
from terminusdb_pydantic import LexicalKey, TerminusModel


class Discipline(TerminusModel):
    __terminus_key__ = LexicalKey("code")

    code: str
    name: str
    description: str | None = None


async def migrate() -> None:
    async with AsyncTerminusClient(
        "http://localhost:6363",
        organization="admin",
        database="edtech",
        username="admin",
        password="root",
    ) as db:
        manager = MigrationManager(db, [Discipline])

        plan = await manager.plan()

        if plan.warnings:
            for warning in plan.warnings:
                print("WARNING:", warning)

        print(plan.render())

        if not plan.empty:
            await manager.apply(
                plan,
                author="schema-bot",
                message="Synchronize schema",
                dry_run=True,
                allow_destructive=plan.destructive,
            )

Current boundaries

The package is not intended to replace TerminusDB's native migration/versioning mechanisms. It only generates and applies plans on top of them.

In 0.1.x:

  • rename intent is not automatically inferred from schema state alone;
  • required-property data backfills are not invented;
  • destructive removals are not silently executed;
  • schema diff behavior is deliberately small and explicit.

Package family

Package Purpose
terminusdb-async Async TerminusDB HTTP client
terminusdb-pydantic Pydantic v2 ↔ JSON-LD and schema generation
terminusdb-migrations Schema diff and migration planning

Development

The project uses uv:

uv sync --group dev
uv run pytest -q
uv build --no-sources

CI tests Python 3.11, 3.12, and 3.13.

Development follows GitHub Flow on GitLab: short-lived branches are merged into main through Merge Requests. See CONTRIBUTING.md.

Versioning

The package is pre-1.0. Internal package compatibility is expressed with ranges such as:

"terminusdb-async>=0.1.0,<1.0.0"
"terminusdb-pydantic>=0.1.0,<1.0.0"

Patch releases do not raise these lower bounds unless they actually depend on new API.

Metadata

Release files for terminusdb-migrations 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for terminusdb-migrations 0.1.1
File Size Uploaded
terminusdb_migrations-0.1.1.tar.gz 9.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for terminusdb-migrations 0.1.1
File Interpreter ABI Platform
terminusdb_migrations-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 17.4 kB

Release files / terminusdb_migrations-0.1.1.tar.gz

Download URL terminusdb_migrations-0.1.1.tar.gz
Size 9.5 kB
Tags Source
SHA-256 checksum
How to use checksums
d58ccbed701cd3348f2b158d59446bc3b4debf56b8e659a13e6404f07095223a
BLAKE2b-256 checksum
How to use checksums
5b5b49f0a690054baddbec5593f948dc349d0f3f663d53c545d4b035bf8b9a33
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.22 {"installer":{"name":"uv","version":"0.12.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / terminusdb_migrations-0.1.1-py3-none-any.whl

Download URL terminusdb_migrations-0.1.1-py3-none-any.whl
Size 7.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9c0db4c20d8b0b88eb5b0e601bc7a7397d5d19c9c65859bc3cefecb7f52fef9f
BLAKE2b-256 checksum
How to use checksums
7444f8f7cceed4c8025996e59362a2fb8994853622b9b73c52facb29484c237d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.22 {"installer":{"name":"uv","version":"0.12.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

0.2.1

2 release files

0.2.0

2 release files

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page