Skip to content

Migrations and Upgrades

SametGoktepe edited this page Jun 17, 2026 · 1 revision

Schema migrations for the outbox table, version upgrade rules across @eventferry/* packages, and the changeset workflow we use to ship releases.

eventferry packages follow independent SemVer — a minor on @eventferry/kafka does not force a bump on @eventferry/postgres. This page tells you what's safe across versions and what to do when an upgrade needs schema work.


Outbox table migrations

Initial install

import { createMigrationSql } from "@eventferry/postgres";  // or @eventferry/mysql

await pool.query(createMigrationSql("outbox"));

createMigrationSql(table) returns a single SQL string covering the table + indexes. Run it once per environment via your existing migration tool (Prisma, Drizzle, Kysely, plain pg, …) — eventferry itself does not run migrations.

Adding columns in your migration runner

The outbox columns eventferry needs are fixed by the package. If you want extra columns for your own bookkeeping (e.g. tenant_id for multi-tenant routing), add them via a separate migration after the eventferry migration:

ALTER TABLE outbox ADD COLUMN tenant_id TEXT;
CREATE INDEX idx_outbox_tenant ON outbox(tenant_id) WHERE status IN (0, 3);

eventferry's claim query selects *, so extra columns flow through to the OutboxRecord you'd see in relay.hooks.onBatchClaimed — but the typed interface doesn't expose them. If you need typed access, cast inside your hook.

Rename the table

Pick whatever name fits — createMigrationSql accepts any identifier:

await pool.query(createMigrationSql("event_outbox_v2"));

const store = new PostgresStore({ pool, table: "event_outbox_v2" });

Use this for multi-domain shards (outbox_orders, outbox_users) or for blue-green table swaps.

Schema diffs across @eventferry/postgres versions

Version Change Migration
3.0.x → 3.1.x Added next_retry_at column for backoff scheduling. ALTER TABLE outbox ADD COLUMN next_retry_at TIMESTAMPTZ;
3.1.x → 3.2.x Added partition_key column for explicit partition routing. ALTER TABLE outbox ADD COLUMN partition_key TEXT;
3.2.x → 3.3.x No schema change. Server-side TZ-safe reaper rewrite — application-side. None.

For a brand-new install, you skip these — createMigrationSql on the latest version emits the current schema directly.

Same shape for @eventferry/mysql.


Version upgrade rules

Same major: safe

Within a major (e.g. @eventferry/kafka@3.4.03.5.0), the public API is additive. New options have defaults that preserve prior behavior; existing options are unchanged.

npm i @eventferry/kafka@latest

No code change required. Read the CHANGELOG (shipped in the npm tarball) for new options worth enabling.

Crossing a major: read the release notes

A major bump signals a breaking change — usually a renamed option, a default flip, or a removed deprecated path. The release notes spell out the migration step.

Example (hypothetical 3 → 4):

// Before (3.x)
new KafkaPublisher({ brokers, transactional: true, transactionalId: "..." });

// After (4.x) — same shape, just confirming the imports still resolve

We aim to make major bumps narrow and infrequent. The current 3.x line has been stable through Phase A, B, and C.

Cross-package compatibility

Adapters declare a peerDependencies floor on @eventferry/core — currently ^3. Mixing @eventferry/core@3.x with @eventferry/postgres@2.x is flagged by npm / pnpm as a peer mismatch. Don't ignore the warning; align the versions.

@eventferry/kafka-iam declares a floor on @eventferry/kafka — currently ^3. Same rule.


Changeset workflow (contributor reference)

eventferry uses Changesets for releases. If you're contributing a PR:

# Inside the repo:
pnpm changeset
# → interactive prompt: which packages, which bump kind, what changed

This drops a markdown file under .changeset/. The release workflow on main:

  1. Sees the changeset → opens / updates a Version Packages PR (bumps versions + writes CHANGELOG.md per package).
  2. Merging that PR → triggers pnpm changeset publish → packages go to npm via OIDC trusted publishing.

Path A independent versioning: a single @eventferry/kafka: minor changeset bumps only @eventferry/kafka (and re-builds its dist with the new core version baked in). No more cascade-major surprises across packages.

@eventferry/all is the meta-package — it picks up minor bumps automatically when any of its inner packages bumps, so consumers can upgrade in lockstep if they want.


Downgrade

Possible but usually pointless. The outbox table is forwards-compatible — a 3.2 table works fine on 3.1 (the new columns are optional). The reverse holds when nothing has been written to the new columns yet.

Real downgrade path: re-deploy the older version, leave the schema unchanged. Don't drop columns — ALTER TABLE DROP COLUMN blocks writes on Postgres and rewrites the table on MySQL.


Renaming the package (rare)

If you forked eventferry and renamed the namespace (e.g. @yourorg/outbox-core), update peerDependencies references in your fork's adapters AND in @yourorg/all's meta-package dependencies. The defineOutbox registry is unaffected — your application code referring to @yourorg/outbox-core resolves to the renamed package.


What's next

Clone this wiki locally