Versioning & Time Travel
Track changes to your data over time and query historical states
Overview
Stabilize ORM provides built-in versioning that tracks every change to your records. When enabled, a <table>_history table stores all historical versions with timestamps, operation types, and version numbers.
Enabling Versioning
Enable versioning on a model by setting versioned: true:
import { defineModel, DataTypes } from "stabilize-orm";
export const Product = defineModel({ tableName: "products", versioned: true, // Enable version tracking columns: { id: { type: DataTypes.STRING, required: true, unique: true }, name: { type: DataTypes.STRING, length: 255, required: true }, price: { type: DataTypes.DECIMAL, required: true }, },});How It Works
When versioning is enabled, Stabilize automatically creates a history table (e.g., products_history) that stores all historical versions. Each version includes:
- All column values at that point in time
- Version number (auto-incremented)
- Operation type (insert, update, delete)
- Valid from/to timestamps
- Modified by and modified at audit fields
Version history is written automatically on create, update, and delete operations.
Time Travel Queries
Query the state of a record at a specific point in time using the asOf method. Pass the record ID and a date:
const repo = orm.getRepository(Product);
// Get product as it existed on a specific dateconst pastDate = new Date("2025-01-01T00:00:00Z");const productAsOf = await repo.asOf(product.id, pastDate);
console.log("Name on Jan 1:", productAsOf?.name);console.log("Price on Jan 1:", productAsOf?.price);Version History
Retrieve the complete change history for a record using history(id):
const repo = orm.getRepository(Product);
// Get all versions of a productconst versions = await repo.history(product.id);
console.log(`Product has ${versions.length} versions`);
versions.forEach(v => { console.log(`Version ${v.version}:`); console.log(` Name: ${v.name}`); console.log(` Price: ${v.price}`); console.log(` Operation: ${v.operation}`); console.log(` Valid from: ${v.valid_from}`);});Rollback
Restore a record to a previous version using rollback(id, version). This creates a new version with the old data:
const repo = orm.getRepository(Product);
// Rollback product #1 to version 2await repo.rollback(product.id, 2);
// The rollback creates a NEW version (version N+1) with version 2's dataconst current = await repo.findOne(product.id);console.log("Current version:", current.version); // Latest version numberconsole.log("Data restored from version 2");Performance Considerations
- Versioning adds storage overhead as all versions are retained
- Write operations are slightly slower due to history table inserts
- Consider archiving old versions for long-running applications
- History queries are indexed on id and version for fast lookups