Guides

TableTheory v2 migration guide

TableTheory v2.0.0 is the planned major release that completes the deprecation cycle from the 2026-07 Product Strengthening Program. It removes duplicate or misleading public surfaces while preserving the DynamoDB-first contract, the P0/P1/P2 scenario corpus, and the single GitHub Releases distribution path.

This page is an implementation-readiness guide. It does not assert that a v2.0.0 release has been cut. Before any stable v2 release, the maintainer must confirm that the 1.x release candidates and stable releases carrying the deprecation notices were published through the normal immutable release lane.

Who is affected

Consumer class What to audit Coordination path
AppTheory Go transaction helpers, typed table/migration options, Python import paths in examples or tests Validate against the v2 RC before promotion; update examples and scaffolds in the same downstream PR.
FaceTheory TypeScript imports for ISR cache helpers and lease helpers; Go transaction recipes Move TypeScript domain helpers to subpath imports and run ISR lease/publish transaction tests against the v2 RC.
KnowledgeTheory Python package imports, Go transaction writes, TypeScript number reads for ledger/telemetry-like values Run data-access integration tests with exact number assertions and canonical tabletheory_py imports.
Autheory Go transactions around identity/session state, encrypted-field read paths, TypeScript/Python imports Validate optimistic-lock and transaction conflict paths; confirm no encrypted field path logs plaintext.
theory-mcp-server Go transaction APIs, Python tabletheory_py package, TypeScript release-state helpers Validate agent memory, idempotency, release-state, and mailbox state flows against DynamoDB Local and the v2 RC.
Pay Theory Payment, settlement, idempotency, and ledger code using transactions or large numbers Maintainer-mediated validation window on the v2 RC; no direct agent outreach.
External open-source consumers All public APIs listed below Changelog, GitHub Release notes, and this guide are the only guaranteed channels.

Release gate checklist

Do not promote a v2 stable release until all of these are true:

  1. A 1.x release containing the deprecation notices has been published as an immutable GitHub Release.
  2. Every Theory Cloud product above has either completed an RC validation pass or has an explicit maintainer waiver.
  3. Pay Theory validation has been coordinated by the maintainer.
  4. The v2 release PR body contains every BREAKING CHANGE: footer from this milestone.
  5. The v2 release notes link this guide and list the exact validation commands used for the release candidate.
  6. The contract suite passes across Go, TypeScript, and Python, including p2.transact_write_atomicity.

Deprecation audit

The v2 removals below are allowed only because each one had a 1.x additive/deprecation predecessor. Repo-local evidence:

v2 change 1.x predecessor evidence v2 issue
Remove Go DB.Transaction, TransactionFunc, and core.Tx docs/development/planning/tabletheory-improvement-program-enumerated-changes-2026-07.md item 1; docs/features/transactions.md warned that db.Transaction(...) and db.TransactionFunc(...) were deprecated in favor of Transact(); docs/development/planning/tabletheory-improvement-program-roadmap-2026-07.md maps item 1 to v2 removal. THE-2453 / TTIP-115
Flip TypeScript number unmarshaling default to precision-safe strings Enumerated item 14 added the opt-in precision-safe mode; ts/docs/core-patterns.md documented the historical lossy default and the numberUnmarshalMode: 'string' migration path; contract-tests/scenarios/p0/10-number-precision.yml pins exact decimal behavior. THE-2454 / TTIP-116
Make tabletheory_py the only Python import package Enumerated item 19 added the tabletheory_py import alias; py/README.md, py/docs/getting-started.md, and docs/runtimes/python/getting-started.md identify tabletheory_py as canonical after the 1.x transition. The legacy theorydb_py package is removed in v2. THE-2455 / TTIP-117
Remove TypeScript root re-exports for domain modules Enumerated item 106 added /facetheory, /release-state, and /lease subpath exports; ts/docs/getting-started.md and docs/runtimes/typescript/getting-started.md marked root imports for those modules deprecated. THE-2456 / TTIP-118
Remove Go opts ...any option variants Enumerated item 69 added concretely typed option APIs and deprecation markers; pkg/core/interfaces.go and internal/theorydb/theorydb.go carried 1.x deprecation notices for the any-typed compatibility surfaces before v2 removal. THE-2457 / TTIP-119
Remove pkg/query.MainExecutor, pkg/query.NewExecutor, and legacy pkg/query.DynamoDBAPI Enumerated item 99 and docs/migration-guide.md documented MainExecutor as a 1.x compatibility/test seam scheduled for next-major removal; production paths already use DB.Model(...), NewWithClient(...), and the runtime executor. THE-2458 / TTIP-120

1. Go transactions: replace Transaction / TransactionFunc with Transact

Breaking change

DB.Transaction(func(*core.Tx) error), ExtendedDB.TransactionFunc(func(any) error), and the legacy core.Tx wrapper are removed. The removed helpers were non-atomic or duplicate transaction surfaces. The only high-level Go write transaction path is now the DynamoDB-backed Transact() builder / TransactWrite(...) helper.

Exact rewrite

Before:

err := db.Transaction(func(tx *core.Tx) error {
    if err := tx.Create(order); err != nil {
        return err
    }
    return tx.Update(account, "balance")
})

After:

err := db.Transact().
    Create(order).
    Update(account, []string{"balance"}).
    Execute()

For callback-style code:

err := db.TransactWrite(ctx, func(tx core.TransactionBuilder) error {
    tx.Create(order)
    tx.Update(account, []string{"balance"})
    return nil
})

Verification steps

  1. grep -R "\.Transaction(" . and grep -R "TransactionFunc" . in the consumer repo; only migration/provenance prose should remain.
  2. Run the consumer’s DynamoDB Local transaction tests.
  3. Run TableTheory make contract-tests and confirm p2.transact_write_atomicity passes for Go, TypeScript, and Python.
  4. For versioned writes, force a version conflict and confirm the whole transaction aborts.

Downstream coordination

  • AppTheory, Autheory, KnowledgeTheory, theory-mcp-server, and Pay Theory must audit Go services for legacy transaction callbacks.
  • FaceTheory must verify ISR transaction recipes use Transact() or direct DynamoDB transaction calls, not the removed wrapper.

2. TypeScript numbers: precision-safe strings are the default

Breaking change

TypeScript now unmarshals DynamoDB N and NS values to canonical decimal strings by default. This prevents JavaScript Number rounding for values such as 9007199254740993 or 0.12345678901234567. Consumers that intentionally want historical lossy JavaScript numbers must opt in.

Exact rewrite

Before v2, exact reads required an option:

const db = new TheorydbClient(ddb, { numberUnmarshalMode: 'string' }).register(LedgerEntry);

In v2, use the default for exact reads:

const db = new TheorydbClient(ddb).register(LedgerEntry);

If a bounded legacy path intentionally wants JavaScript Number coercion:

const lossyDb = new TheorydbClient(ddb, { numberUnmarshalMode: 'number' }).register(LedgerEntry);

Verification steps

  1. Search for arithmetic performed directly on fields read from DynamoDB N/NS attributes.
  2. Convert explicit arithmetic to parse with the consumer’s chosen decimal library or BigInt where appropriate.
  3. Add a fixture for 9007199254740993 and a high-precision decimal; assert the read value is the original string.
  4. Run cd ts && npm run check and TableTheory make contract-tests.

Downstream coordination

  • KnowledgeTheory, Pay Theory, and any ledger/telemetry consumer must validate large-number reads first.
  • FaceTheory/AppTheory helpers that use epoch milliseconds or counters can opt into number only after confirming values remain within JavaScript’s safe range.

3. Python package: use tabletheory_py

Breaking change

tabletheory_py is the only Python import package. The legacy theorydb_py package was deprecated during the 1.x transition and is removed in v2; there is no warning shim in the v2 package.

Exact rewrite

Before:

from theorydb_py import ModelDefinition, Table, theorydb_field
from theorydb_py.schema_migration import auto_migrate

After:

from tabletheory_py import ModelDefinition, Table, theorydb_field
from tabletheory_py.schema_migration import auto_migrate

Verification steps

  1. grep -R "theorydb_py" . in the consumer repo; update imports except historical migration notes.
  2. Install the v2 wheel from GitHub Releases and run python - <<'PY'\nimport tabletheory_py; print(tabletheory_py.__version__)\nPY.
  3. Confirm python - <<'PY'\nimport theorydb_py\nPY fails with ModuleNotFoundError after the consumer no longer depends on the legacy path.
  4. Run Python unit/integration tests against DynamoDB Local.
  5. Confirm packaged code, generated DMS models, Lambda handlers, and examples import only tabletheory_py.

Downstream coordination

  • KnowledgeTheory, Autheory, theory-mcp-server, and Pay Theory Python services must update imports before the v2 stable release.
  • External consumers should be directed to the GitHub Release wheel and this guide; do not suggest PyPI.

4. TypeScript domain modules: use package subpaths

Breaking change

The root TypeScript barrel is now generic ORM only. FaceTheory ISR helpers, release-state helpers, and lease helpers are exported exclusively from subpaths.

Exact rewrite

Before:

import { FaceTheoryIsrMetaStore, transitionReleaseState, LeaseManager } from '@theory-cloud/tabletheory-ts';

After:

import { FaceTheoryIsrMetaStore } from '@theory-cloud/tabletheory-ts/facetheory';
import { transitionReleaseState } from '@theory-cloud/tabletheory-ts/release-state';
import { LeaseManager } from '@theory-cloud/tabletheory-ts/lease';

Verification steps

  1. grep -R "@theory-cloud/tabletheory-ts'" . and inspect any imports of FaceTheory, release-state, or lease symbols.
  2. Run npm run typecheck (or the consumer equivalent) to catch removed root exports.
  3. Run affected ISR, release-state, and lease tests.
  4. Run TableTheory cd ts && npm run check.

Downstream coordination

  • FaceTheory is the primary consumer of /facetheory and /lease; validate ISR regeneration and lease release flows.
  • Release automation and theory-mcp-server should validate /release-state imports.

5. Go typed options: remove opts ...any

Breaking change

Go table/migration option APIs no longer accept arbitrary opts ...any. Call sites must pass the concrete schema.AutoMigrateOption or schema.TableOption values that the typed methods expect.

Exact rewrite

Before (boxed options compiled because the API accepted opts ...any):

migrationOpts := []any{schema.WithTargetModel(&UserV2{})}
err := db.AutoMigrateWithOptions(&UserV1{}, migrationOpts...)

tableOpts := []any{schema.WithBillingMode(types.BillingModePayPerRequest)}
err = db.CreateTable(&User{}, tableOpts...)

After (make the option slices concrete):

migrationOpts := []schema.AutoMigrateOption{schema.WithTargetModel(&UserV2{})}
err := db.AutoMigrateWithOptions(&UserV1{}, migrationOpts...)

tableOpts := []schema.TableOption{schema.WithBillingMode(types.BillingModePayPerRequest)}
err = db.CreateTable(&User{}, tableOpts...)

Direct calls with typed option values keep the same call shape:

err := db.AutoMigrateWithOptions(&UserV1{}, schema.WithTargetModel(&UserV2{}))
err = db.CreateTable(&User{}, schema.WithBillingMode(types.BillingModePayPerRequest))

Verification steps

  1. Search for []any or interface{} values passed to AutoMigrateWithOptions or CreateTable.
  2. Let go test ./... catch any remaining non-concrete options at compile time.
  3. Run schema migration/table creation smoke tests against DynamoDB Local.

Downstream coordination

  • AppTheory and KnowledgeTheory scaffolds should update any helper that stores schema options in []any.
  • Pay Theory should validate any custom table-provisioning tooling before v2 stable.

6. Go query executor: MainExecutor is removed

Breaking change

pkg/query.MainExecutor, pkg/query.NewExecutor, and the legacy pkg/query.DynamoDBAPI executor seam are removed. The production execution stack is the runtime executor reached through tabletheory.New(...), tabletheory.LambdaInit(...), DB.Model(...), and tabletheory.Model(...). Tests that need client injection should use the public tabletheory.NewWithClient(...) constructor with tabletheory.DynamoDBAPI / session.DynamoDBAPI instead of importing a seam from pkg/query.

Exact rewrite

Before:

exec := query.NewExecutor(ddb, ctx)
compiled := &core.CompiledQuery{TableName: "users", Operation: "query"}
var out []User
err := exec.ExecuteQuery(compiled, &out)

After:

db, err := tabletheory.NewWithClient(session.Config{Region: "us-east-1"}, ddb)
if err != nil {
    return err
}
var out []User
err = db.WithContext(ctx).
    Model(&User{}).
    Where("PK", "=", "USER#1").
    All(&out)

For test code that used MainExecutor only to exercise unmarshaling, call query.UnmarshalItem(...) or query.UnmarshalItems(...) directly, or use the state-backed fake where the test needs behavior rather than a low-level executor seam.

Verification steps

  1. grep -R "MainExecutor\|NewExecutor\|query.DynamoDBAPI" . in the consumer repo; only migration prose should remain.
  2. Replace low-level compiled-query tests with DB.Model(...) tests over DynamoDB Local or the TableTheory fake.
  3. Run make test-unit and any package-level coverage gates.

Downstream coordination

  • Internal Theory Cloud packages should remove direct executor tests before adopting v2.
  • External consumers should not construct execution stacks manually; if a use case cannot be expressed through DB.Model(...), open a TableTheory issue instead of reaching around the runtime.