ev connects to any relational database,
infers entities from the foreign key graph, and installs
lightweight triggers to capture every INSERT, UPDATE,
and DELETE. Changes are grouped into versioned
changesets you can browse, query, and export.
changeset v3 [tx: 8a3f2b1c] 2026-02-15 14:23:07 UTC
tables: course, course_upsell
-- course (id=42)
UPDATE endDate: 2026-05-01 -> 2026-06-01
-- course_upsell (id=18)
INSERT courseId=42, licenses=10
changeset v2 [tx: 7b2e1a0d] 2026-02-10 09:15:33 UTC
tables: course
-- course (id=42)
UPDATE name: Intro to SQL -> Advanced SQL
changeset v1 [tx: 6c1d0f9e] 2026-02-01 11:00:00 UTC
tables: course
-- course (id=42)
INSERT name=Intro to SQL, startDate=2026-03-01
Up and running in under five minutes.
# One-liner install (Linux / macOS)
curl -fsSL https://raw.githubusercontent.com/sgmonda/entity-versioning/main/install.sh | sh
This will prepare ev command, so you
can start using entity versioning in your databases.
A simple ev --help will show you all
available commands and options. Later, you could
upgrade to a newer version with a simple
ev upgrade, or even self-uninstall it
completely using ev uninstall.
Most audit-log solutions require you to instrument your
application — ORM hooks, middleware, custom triggers
written by hand. ev takes a different approach.
It reads your schema and figures out the rest. No configuration beyond a connection string.
No hand-written SQL, no ORM plugins. Lightweight triggers that capture every change automatically.
A course with its upsells and services is tracked as one logical unit. Changes are grouped semantically.
Everything you need to build a complete audit trail, without touching your application code.
Works entirely through database triggers. No ORM plugins, no middleware, no code changes.
Analyzes your FK graph to discover entities and their child tables automatically.
Operations within the same DB transaction are grouped into a single changeset.
DDL hooks capture ALTER TABLE events and record schema changes alongside data changes.
ev teardown removes everything. All
objects are namespaced under __ev_.
Pluggable connector interface. PostgreSQL and MySQL ship built-in. Community connectors welcome for MariaDB, SQL Server, SQLite, and more.
Three commands. Five minutes. Full audit trail.
Point ev at your database. It introspects the schema, analyzes the FK graph, and infers entities automatically.
$ ev init --host localhost --port 5432
--database myapp
Even if they are inferred from foreign keys, you can still customize them. Add or remove tables, define parent-child relationships, and exclude columns from tracking.
$ ev entities
Install changelog tables, DML triggers, and DDL hooks with a single command. Your database is now being versioned.
$ ev startQuery the full change history of any entity instance. Filter by time, version, or export as JSON.
$ ev log --entity course --id 42
A complete workflow from initialization to change log, showing entity inference and change tracking.
# Initialize — auto-discovers entities from your schema
$ ev init --host localhost --port 5432 --database edtech --engine postgres
Introspecting schema...
Found 14 tables, 18 foreign keys
Inferred 3 entities:
course root: course children: course_upsell, course_service
billing root: billing children: billing_line
class root: class children: class_evaluations, class_history
Config written to ev.config.yaml
# Start tracking — installs triggers on all entity tables
$ ev start
Installed 9 triggers across 3 entities
DDL hooks: installed (event trigger)
Tracking active.
# Your app makes changes as usual — ev captures everything
$ ev log --entity course --id 42
changeset v2 [tx: 7b2e1a0d] 2026-02-10 09:15:33 UTC
tables: course
-- course (id=42)
UPDATE name: Intro to SQL -> Advanced SQL
changeset v1 [tx: 6c1d0f9e] 2026-02-01 11:00:00 UTC
tables: course
-- course (id=42)
INSERT name=Intro to SQL, startDate=2026-03-01
# Clean up — zero residue
$ ev teardown --confirm
Dropped 9 triggers, 3 functions, 2 tables, 1 event trigger
All __ev_ objects removed.
Engine-agnostic core with a pluggable connector interface. Add new databases without touching business logic.
┌───────────────────────────────────────────────────────┐
│ CLI (ev) │
│ init · entities · start · stop · status · log · ... │
├───────────────────────────────────────────────────────┤
│ Core Engine │
│ Schema Analyzer · Entity Resolver · Changes Builder │
├───────────────────────────────────────────────────────┤
│ Connector Interface │
│ introspect · triggers · ddl_hooks · query · health │
├──────────────────┬──────────────┬─────────────────────┤
│ PostgreSQL │ MySQL │ Community │
│ (built-in) │ (built-in) │ connectors │
└──────────────────┴──────────────┴─────────────────────┘
│
▼
┌──────────┐
│ Your DB │
└──────────┘
Parses commands, reads config, delegates to the core engine. No business logic here.
FK graph analysis, entity resolution, changeset building. Engine-agnostic — never touches SQL.
Abstract contract: introspect, triggers, DDL hooks, query, health. Clean separation of concerns.
Engine-specific implementations loaded dynamically. Add your own for any relational database.