Shadow Execution
Shadow execution settles what static review cannot: what actually happens when this runs? From a script or an approval request, Shadow Run provisions a disposable twin of the target, applies the pending script, diffs the schema before and after, and tears the twin down, surfacing the real effect and the real error without touching the target.
Once a run has started, the control shows its latest result, passed, failed or stopped, on the script in Migration Scripts and on its approval request, and opens the full run when clicked.
Pipeline
- Provision, a synthetic twin on the target's server (or a dedicated sidecar, per deployment).
- Build, source schema rebuilt into the twin with planner statistics for fidelity, including user-defined functions and aggregates, so views that use them are copied too. Anything that still cannot be copied is listed under Notes. No production rows by default.
- (Optional) Sample, Run with Sample Data copies a bounded random sample of the touched tables (and FK parents) so data-dependent migrations (backfills, UPDATE/DELETE) operate on representative data and report realistic counts. Opt-in per run because sampled rows are real data.
- Run, the script executes in a transaction under statement and lock timeouts; per-statement success/exact error, duration, and rows affected are recorded.
- Diff, twin schema compared before vs. after (the Flight Recorder diff engine), surfacing added/removed/altered objects: tables, views, sequences and routines on the SQL engines, keyspaces' tables and views on Cassandra, collections, views and their index counts on MongoDB, labels and relationship types on Neo4j, indices and aliases on Elasticsearch, and key patterns on Redis.
- Teardown, the twin is always dropped; a background sweeper force-drops any twin outliving its run.
Honesty Contract
The panel shows the stage (Preparing the twin, Running the script, then Passed, Failed or Stopped), the twin it used and how long it took, each preflight check in words, every statement with its result, the schema changes and notes. While the run is going it says the comparison appears when the run finishes; once it has finished it says whether the twin was removed, and on a failure why it failed.
A shadow run executes against a schema-faithful, data-sampled twin. It proves the migration applies cleanly and what it changes structurally; it does not prove behavior at full production volume or on real data distributions. Every result carries this caveat, because a dry run implying fidelity it lacks is worse than none. On failure the panel shows the exact SQL error, the single most valuable output.
Safety Model
The source is only ever read, schema introspection and, when sampling, SELECTs on a session pinned read-only, so the feature physically cannot write to it, plus the server-level create/drop of the twin. The script itself only ever touches the throwaway twin, except on Neo4j, where it runs on the live graph inside transactions that are rolled back. Twin credentials are ephemeral and never stored; no sampled row values are persisted to the record (counts only). Twin mode, timeouts, sample size, and sweep age are documented under Configuration.
The Twin on Each Engine
- PostgreSQL, TimescaleDB and CockroachDB, a new database on the same server, with the source's planner statistics.
- MySQL and MariaDB, a new database on the same server. The empty twin has no planner statistics, so sample data when realistic plans matter.
- SQL Server, a new database on the same server (needs
CREATE ANY DATABASE); sampled rows keep their identity values. - Oracle, a temporary user holding a copy of the source schema. The connection user needs
CREATE USER,DROP USERand, withADMIN OPTION, the privileges the twin user is given (CREATE SESSION,CREATE TABLE,CREATE VIEW,CREATE SEQUENCE,CREATE PROCEDURE,CREATE TRIGGER,CREATE TYPE,CREATE SYNONYM); the preflight names any that are missing. - SQLite, a temporary file with the source's schema and
ANALYZEstatistics, deleted afterwards. - MongoDB, a new database on the same server with the source's collections, validators and indexes.
- Cassandra, a new keyspace with the source keyspace's replication, tables, indexes, types and materialized views.
- Redis, a key prefix on the same database: every key a command names is moved under the prefix, sampling copies the matching keys under it, and teardown removes every prefixed key. Commands whose keys cannot be located, such as
EVALorFLUSHDB, fail the preflight. - Elasticsearch, copies of the indices the script names, with their mappings and settings, under a name prefix; aliases the script adds are prefixed too, and sampling reindexes up to the sample size.
- Neo4j, the script runs on the live graph inside transactions that are always rolled back, so nothing is committed; schema statements and data statements run in separate transactions, as Neo4j requires. The schema comparison is therefore empty and each statement's counts show what it would change.
Where the twin shares a server with the source, a script that names the source database, schema or keyspace (for example shop.orders on MySQL) fails the preflight, since it would reach past the twin; write the objects without it.