Skip to content

Database

Single PostgreSQL instance. All v7 services connect via GORDON_DATABASE_URL (or a service-scoped DSN using a least-privilege role).

GORDON_DATABASE_URL=postgresql://gordon:gordon_dev@localhost:5432/gordon

search_path = trading, market_data, public — queries use bare table names.

Schemas

SchemaBacked upWritersNotes
market_dataNo (re-fetchable, ~7 GB)gordon-data onlySole writer enforced via gordon_lab_reader role revoking INSERT/UPDATE/DELETE
tradingYes — hourly restic to srv-coregordon-executor, gordon-risk, gordon-manager, gordon-botCore business data
busNogordon-bus (outbox)bus.outbox for NATS dual-write
publicsqlx internals_sqlx_migrations only

DB roles (least-privilege)

Roles are provisioned by gordon-migrate. Each service connects using its own role.

RolePrivilegesUsed by
gordon_data_writerINSERT/UPDATE on market_data.*gordon-data
gordon_executorINSERT/UPDATE on trading.orders, trading.trades, trading.order_events, trading.fill_events; INSERT + UPDATE on bus.outbox; EXECUTE on increment_fencegordon-executor
gordon_riskSELECT on trading.*; INSERT on trading.risk_events, trading.risk_audit_log; column-level UPDATE on bot_configs.desired_state onlygordon-risk
gordon_managerINSERT on trading.bot_configs, trading.runs, trading.equity_points, trading.bot_deploys; reads via named views (v_klines_reader, v_metrics_reader, v_macro_reader, v_funding_rates_reader, v_open_interest_reader)gordon-manager
gordon_botINSERT on trading.order_intents, trading.bot_leases, trading.signals; advisory-lock-based leasegordon-bot
gordon_lab_readerSELECT only — INSERT/UPDATE/DELETE revoked on all schemasgordon-lab
gordon_drift_readerSELECT only — for drift-check toolingdrift scripts

Roles and grants are defined in migration 0008_roles_and_grants.sql and extended by later migrations. The grant matrix is enforced by cargo test -p gordon-migrate --test grant_matrix.

Named reader views (migration 0019)

Gordon-manager and gordon-risk read market_data.* through named views rather than direct table access. The gordon_manager and gordon_risk roles have SELECT revoked on the underlying tables; access goes through:

ViewPurpose
v_klines_reader1m + precomputed klines for backtest and bot warmup
v_metrics_readerDerivatives metrics (OI, funding z-scores)
v_macro_readerFRED macro data (DXY, VIX)
v_funding_rates_reader8h funding rates
v_open_interest_readerOI snapshots
v_gex_readerGamma exposure snapshots (migration 0028)

market_data tables

TablePurpose
spot_klines1m canonical klines from Binance spot; higher TFs precomputed by gordon-data
perp_klinesPerpetual futures klines
funding_rates8h Binance funding rates per symbol
open_interestHourly OI snapshots
metricsDerived metrics (VPIN, long/short ratio, etc.)
fear_greedDaily Fear & Greed index from alternative.me
stablecoin_supplyDaily stablecoin supply ratio (SSR)
gamma_exposureGEX aggregate snapshots (flip, walls, regime)
gamma_exposure_strikesGEX per-strike profile
source_freshnessPer-source ingest liveness (written by gordon-data scheduler)
macro_dataFRED macro series (DXY, VIX, etc.)

trading tables

TablePurpose
runsBacktest, paper, and live trading sessions
tradesIndividual exchange fills
roundtripsEntry-exit pairs derived from trades
signalsStrategy signal log
equity_pointsPortfolio equity curve over time
performance_snapshotsAggregate performance metrics per run
ordersOrder state machine (submitted → acked → filled/rejected/cancelled)
order_intentsIntent queue from gordon-bot to gordon-executor
order_eventsState-transition events per order
fill_eventsFill records from the exchange
bot_configsBot lifecycle config (desired_state, image_tag, strategy_params)
bot_leasesAdvisory-lock lease table (one row per active bot)
bot_deploysGreen/blue deploy state machine
bot_strategy_statePersisted strategy state per bot
reconcile_runsExecutor reconcile results on restart
risk_stateHalt latch (halted boolean), cleared by POST /risk/resume
risk_eventsCircuit-breaker trip audit log
risk_audit_logOperator action audit (flatten, resume, pause)
risk_configRuntime-tunable breaker thresholds
bot_commandsCommands from gordon-risk to gordon-executor/bot (flatten, pause)
bot_eventsLifecycle events published by bots and executor
positionsCurrent open positions (updated by positions_apply_trade() trigger)
pipeline_stateLISTEN/NOTIFY consumer cursor offsets
symbol_subscriptionsPer-bot symbol subscription records
service_deploysService-level deploy records
shadow_ordersShadow compare orders during green/blue deploy
agg_tradesAggregated trade data

bus tables

TablePurpose
bus.outboxDual-write buffer for NATS delivery. Gordon-bus leader drains this.

Migrations

Source of truth: gordon-migrate/migrations/. 38 migrations as of 2026-05-17.

Latest migrations:

  • 0036_daily_notional_caps.sql — per-bot and global UTC-day rolling notional cap tables
  • 0037_audit_event_flatten_crashed_during.sql — extend audit event types
  • 0038_runs_strategy_code_revision.sql — strategy code revision column on runs

Run via gordon-migrate one-shot container (ghcr.io/dlepaux/gordon-migrate). Services gate on service_completed_successfully in _sqlx_migrations.

Conventions

CategoryConventionExample
TimestampsBIGINT, UTC milliseconds1672531200000
SymbolsBinance-native, no slashBTCUSDT
PricesDOUBLE PRECISION42150.50
Quantities, feesNUMERIC0.00150000
Enum stringsLowercase with CHECK constraints'long', 'short', 'running'
Foreign keysON DELETE CASCADE to runs(id)All per-run tables

Gordon — keep compounding without blowing up