Files
trade-docs/doc/migration-todo.md

30 KiB

Trade Migration Plan: k3s on mevnode alongside agave

Date: 2026-04-12

Migration Revision Baseline

  • Accepted migration baseline revision: R001
  • R001 means the currently working trade application running on k3s before migration cutover.
  • The current source runtime for R001 is the live trade-staging stack on mevnode_bot.
  • The first migration target is not a redesign. It is a faithful reconstruction of R001 on the target k3s environment.
  • Functional changes, refactors, topology changes, and cleanup should be treated as later revisions after R001 is reproducible.
  • During reconstruction, every manifest, secret mapping, image reference, and host dependency should be mapped against R001.

Goal

  • Prepare migration of the trade system to k3s on host mevnode (sol) in parallel with agave-validator.
  • Do not degrade validator stability, memory headroom, or disk/I/O for ledger and accounts.

Current Findings

  • mevnode_bot is reachable again after restart.
  • Previous reset on mevnode_bot looks like ACPI power state transition occurred.
  • I did not find a clear OOM, kernel panic, watchdog, or I/O error trail explaining the previous host reset.
  • k3s on mevnode_bot is up and the node is Ready.
  • The main runtime failure is not the host itself but the DLOB publishers:
    • dlob-publisher-hot is 0/1
    • dlob-publisher-all is 0/1
    • both have very high restart counts
    • both fail startup/liveness probes
  • Publisher logs show Redis connectivity problems:
    • ClusterAllFailedError: Failed to refresh slots cache
    • None of startup nodes is available
  • dlob-redis currently exposes a single ClusterIP endpoint on 6379, while the publishers behave like cluster-aware Redis clients.
  • Hasura, trade-api, trade-frontend, trade-ingestor, postgres, and the writer pods are currently up.
  • trade-ingestor had transient fetch failures after reboot, then resumed inserts.
  • There is a persistent warning in k3s about missing image pull secret gitea-registry.

Resource Picture: mevnode

  • CPU: 32 vCPU
  • RAM total: about 186 GiB
  • RAM available: about 111 GiB at check time
  • Swap total: about 31 GiB
  • Swap used: about 13 GiB
  • Root filesystem /: btrfs, about 1.8 TiB total, about 1.6 TiB free
  • /data/ledger lives on a separate 1.8 TiB NVMe device.
  • /data/state lives on another separate 1.8 TiB NVMe device.
  • The current candidate place for trade persistent storage on sol is the root NVMe filesystem /, not the validator ledger or accounts devices.
  • agave-validator RSS: about 129 GiB
  • agave-validator is already a heavy resident workload and must remain the priority workload on this host.

Resource Picture: mevnode_bot

  • Root filesystem /: ext4 on md RAID, about 3.6 TiB total, about 2.8 TiB free
  • Current memory use after reboot is low, but this is not the main constraint.
  • The main storage warning is current k3s data growth:
    • /var/lib/rancher/k3s: about 593 GiB
    • /var/lib/rancher/k3s/storage/...data-postgres-0: about 585 GiB
    • the related PVC is declared as only 20Gi
  • This means the current local-path storage setup does not give a meaningful hard size limit in practice.
  • The target Gitea organization trade-next now exists.
  • The target repository set now exists in trade-next:
    • trade-api
    • trade-frontend
    • trade-ingestor
    • trade-bot
    • trade-dlob
    • trade-gitops
    • trade-host-iac
    • trade-docs
  • The current live component-to-repository boundary was documented in trade-next/trade-docs/doc/k3s-component-repo-map.md.
  • We have not yet reconstructed the current live trade-staging manifests and host drift into trade-gitops and trade-host-iac.
  • The first canonical bootstrap module now exists in trade-next/trade-gitops: bootstrap/gitea-actions.
  • An organization-scoped Gitea Actions runner for trade-next is now online on sol and can reach the target k3s cluster using the K3S_KUBECONFIG_B64 org secret.
  • The first canary environment now exists in trade-next/trade-gitops under environments/sol/trade-r001-canary.
  • Namespace trade-r001-canary is live on sol with initial quota and limit guardrails, and can reach the shared Postgres and Redis services in trade-infra.
  • The first application surface for R001 is now live in trade-r001-canary: Hasura, trade-api, and trade-frontend.
  • The target host Postgres on sol now has TimescaleDB installed and a matching application database/user provisioned for R001.
  • trade-ingestor is now live in trade-r001-canary on sol in a schema-compatible canary mode that reads from dlob_stats_latest.
  • Current live trade-staging drift was confirmed for trade-ingestor: the live script now reads dlob_hot_derived_latest and dlob_all_derived_latest, but that derived writer chain has not yet been reconstructed in the sol canary schema.
  • agave RPC on sol is currently healthy; repeated samples after the canary rollout show slot lag of about 2 versus api.mainnet-beta.solana.com.

Migration Risks

  • Risk 1: moving the current storage model unchanged to mevnode can silently consume hundreds of GiB on the host root filesystem.
  • Risk 2: agave-validator already uses most of the memory footprint on mevnode; uncontrolled k3s workloads can force more swap or destabilize validator performance.
  • Risk 3: if trade workloads share disks or I/O paths with ledger/accounts, validator performance may degrade.
  • Risk 4: current publisher instability must be fixed before migration, otherwise we would move a broken topology.
  • Risk 5: missing gitea-registry secret can break future image pulls and cold-start behavior.

Plan

1. Reconstruct the current live mevnode_bot state into canonical Git/IaC

  • Map each live trade-staging object to a target repository and file path.
  • Split application code, Kubernetes manifests, and host-level infrastructure into separate Git sources of truth.
  • Capture the current live deltas that are not present in local repos or in ~/trade-k8s.
  • Prefer a new Gitea organization for the migration target instead of long-lived migration branches in existing repos.
  • Treat live k3s as input for reconstruction, not as a YAML dump to mirror blindly.

2. Stabilize the current trade stack on mevnode_bot

  • Fix dlob-publisher-hot.
  • Fix dlob-publisher-all.
  • Verify Redis mode and publisher Redis client mode are aligned.
  • Confirm all trade-staging pods become healthy after a full restart.

3. Audit storage before any migration

  • Measure actual PostgreSQL data size inside the current PVC.
  • Determine how much of the 585 GiB is real database payload versus local-path overhead.
  • Identify retention candidates for historical data, derived tables, logs, and caches.
  • Decide what data must move and what can be rebuilt.

4. Define target storage layout on mevnode

  • Do not place trade persistent data on the same critical paths as agave ledger/accounts.
  • Do not rely on the current local-path behavior without hard operational limits.
  • Choose a dedicated storage path or dedicated device for trade state.
  • Set explicit quotas/limits and monitor actual bytes used on disk.

5. Define resource isolation on mevnode

  • Reserve headroom for agave-validator.
  • Add CPU and memory requests/limits for trade workloads.
  • Keep low-priority or bursty trade jobs away from validator-critical resources.
  • Treat publisher and DB workloads as separate scheduling/priority classes.

6. Recreate the missing operational prerequisites

  • Restore or recreate gitea-registry image pull secret.
  • Verify registry pull works after node reboot and after cache eviction.
  • Verify secrets for RPC, gRPC, Hasura, Postgres, and frontend auth are reproducible.

7. Prepare a staged migration

  • Start with a minimal canary namespace on mevnode.
  • Bring up infrastructure first: Redis, Postgres, Hasura.
  • Then bring up API and frontend.
  • Migrate publishers and ingest only after storage and Redis behavior are validated.
  • Keep mevnode_bot as rollback target until the new stack is stable.

8. Add migration validation checks

  • Host-level: memory, swap, disk, inode, and load checks.
  • Agave-level: slot lag, RPC health, and validator memory trend.
  • Trade-level: pod readiness, Redis health, Hasura health, API health, publisher health, ingest success.
  • End-to-end: UI, API, DLOB data freshness, and bot-related paths.

Immediate Next Actions

  • Map the current live trade-staging state into target Git repositories and IaC paths.
  • Start the first canonical inventory pass into trade-gitops and trade-host-iac.
  • Inspect publisher deployment/env and confirm whether Redis should be single-instance or cluster mode.
  • Inspect Redis server configuration and topology in trade-staging.
  • Measure real Postgres database size inside the trade PVC.
  • Draft target disk placement for trade data on mevnode.
  • Decide minimum safe RAM headroom to keep free for agave-validator.

Open Questions

  • Which repositories belong in the new Gitea organization, and which existing repos should stay only as upstream history?
  • Do we need a clean cutover into a new organization, or only a temporary compatibility layer with the current repos?
  • Is the intended Redis topology for trade a single Redis instance or Redis Cluster?
  • Which trade datasets are required to migrate, and which can be rebuilt from source?
  • Where exactly on mevnode should persistent trade storage live?
  • What is the acceptable validator memory floor and swap ceiling during trade rollout?

Chapter 2

01. Define hard database and cache constraints

  • In progress.
  • Storage limits for Postgres and Redis must be enforced by the real storage backend, not only declared in Kubernetes manifests.
  • In core Postgres, the hard stop for total on-disk growth should still be treated as the filesystem quota; PostgreSQL itself should add earlier guardrails before that limit is reached.
  • Postgres must not be able to grow beyond the actually allocated disk budget.
  • Postgres must have explicit CPU and memory requests/limits consistent with host headroom.
  • Postgres should use temp_file_limit so large sorts and hashes fail before they can consume uncontrolled temporary disk space.
  • Postgres must have operating thresholds for free disk, WAL growth, autovacuum, and table/index bloat.
  • Postgres should use bounded max_wal_size and, if replication slots are present, bounded max_slot_wal_keep_size, while treating WAL limits as early control signals rather than the final hard stop.
  • Postgres should have retention and pruning policies for time-series data so historical chunks are dropped before storage pressure reaches the OS quota.
  • Postgres should have an operational read-only switch prepared, so new write traffic can be stopped before the filesystem quota is actually hit.
  • Redis must have explicit memory limits and an intentional eviction/persistence policy.
  • Redis must use explicit maxmemory below the container memory limit and must set an intentional maxmemory-policy instead of relying on the default unlimited dataset behavior.
  • Redis should set maxmemory-clients so client buffers cannot grow without bound under connection pressure.
  • Redis must not be allowed to consume unbounded RAM or disk on the target host.
  • Database and cache capacity alerts must fire before any hard limit is reached, not after the filesystem is already effectively full.
  • Full-disk and out-of-memory behavior for Postgres and Redis must be tested before application cutover.
  • Done on 2026-04-12: installed PostgreSQL 16 and Redis 7 on sol and started both services.
  • Done on 2026-04-12: moved Postgres data directory to /srv/trade/postgres/16/main.
  • Done on 2026-04-12: applied Postgres guardrails on sol: shared_buffers=2GB, effective_cache_size=8GB, work_mem=16MB, maintenance_work_mem=512MB, temp_file_limit=8GB, max_wal_size=4GB, min_wal_size=512MB, max_slot_wal_keep_size=2GB, idle_in_transaction_session_timeout=10min.
  • Done on 2026-04-12: prepared and tested operational Postgres read-only switch at /usr/local/bin/trade-postgres-readonly.
  • Done on 2026-04-12: applied Redis guardrails on sol: maxmemory=384MB, maxmemory-clients=64MB, maxmemory-policy=noeviction, save \"\", appendonly no.
  • Done on 2026-04-12: initialized Redis as a single-node cluster with all 16384 slots assigned and cluster_state: ok.

02. Reconstruct the current live mevnode_bot and trade-staging state into canonical Git/IaC in a new Gitea organization

  • Live k3s is the input for reconstruction, not the final source of truth.
  • Split application repositories, Kubernetes manifests, and host IaC into separate repositories.
  • Prefer a new Gitea organization over long-lived migration branches in existing repositories.
  • Recommended target organization name: trade-next.
  • Target repository set in trade-next: trade-api, trade-frontend, trade-ingestor, trade-bot, trade-dlob, trade-gitops, trade-host-iac, trade-docs.
  • Keep the current repository names where possible and change only the organization to reduce migration risk.
  • Use trade-gitops as the GitOps source for k3s manifests and trade-host-iac for host-level IaC, SSH, storage, and operations.
  • Record every current live drift before moving workloads.
  • Done on 2026-04-12: trade-next was created and the target repositories now exist.
  • Done on 2026-04-12: the live component boundary map was written to trade-next/trade-docs/doc/k3s-component-repo-map.md.
  • Done on 2026-04-12: bootstrapped trade-next/trade-gitops with the first runnable IaC module for sol under bootstrap/gitea-actions.
  • Next for item 02: reconstruct the live trade-staging objects, overlays, secrets wiring, and host-specific drift into trade-gitops and trade-host-iac.

03. Fix dlob-publisher-hot startup, readiness, and liveness

  • Pending.

04. Fix dlob-publisher-all startup, readiness, and liveness

  • Pending.

05. Confirm whether trade Redis is meant to run as a single instance or as Redis Cluster

  • Pending.

06. Align publisher Redis client mode with the actual deployed Redis topology

  • Pending.

07. Restore or recreate the missing gitea-registry image pull secret

  • Pending.

08. Verify that image pulls work after node reboot and on a cold start

  • Pending.

09. Measure the real PostgreSQL data size inside the current trade PVC

  • Pending.

10. Explain why the declared 20Gi PVC currently consumes about 585 GiB on disk

  • Pending.

11. Decide which trade datasets must be migrated and which can be rebuilt

  • Pending.

12. Define a dedicated storage path or device for trade data on mevnode

  • Done on 2026-04-12.
  • Current preferred target layout on sol is to place trade persistent storage on the root NVMe filesystem /, because validator ledger and validator state already have their own dedicated devices.
  • Do not place Postgres or Redis on /data/ledger or /data/state.
  • Reserve a dedicated 1 TiB storage budget for Postgres on sol as the first target sizing for R001.
  • Reserve a separate small storage budget for Redis on sol, initially 2 GiB unless persistence requirements change.
  • Prefer a dedicated path such as /srv/trade/postgres and /srv/trade/redis over implicit storage under /var/lib/rancher/k3s/storage.
  • On the current btrfs root filesystem, the preferred implementation path is a dedicated subvolume plus enforced qgroup quota for each persistent component.
  • Done on 2026-04-12: created btrfs subvolumes on sol at /srv/trade, /srv/trade/postgres, and /srv/trade/redis.

13. Define hard storage quotas and monitoring for trade data on mevnode

  • In progress.
  • Use enforceable limits, not only declarative PVC sizes without backend enforcement.
  • Add warning and critical thresholds for disk usage, inode usage, and PVC growth.
  • Target hard quota for Postgres on sol: 1 TiB.
  • Target hard quota for Redis on sol: 2 GiB unless later requirements justify persistence growth.
  • Keep enough unallocated free space on the root NVMe for the OS, k3s, container images, logs, and rollback operations after trade quotas are reserved.
  • Done on 2026-04-12: enabled btrfs qgroups on / at sol and applied hard quotas of 1 TiB to /srv/trade/postgres and 2 GiB to /srv/trade/redis.

14. Define CPU and memory reservations that protect agave-validator

  • Pending.

15. Define the minimum safe free RAM headroom on mevnode during rollout

  • Pending.

16. Define the maximum acceptable swap usage on mevnode during rollout

  • Pending.

17. Install and bootstrap k3s on mevnode

  • Done on 2026-04-12.
  • Define the target k3s installation model on mevnode.
  • Define the target storage class, host paths, and bootstrap dependencies needed before application rollout.
  • Verify that the base cluster, registry access, namespaces, and secret distribution work before any application components are installed.
  • Done on 2026-04-12: installed single-node k3s on sol as v1.34.6+k3s1.
  • Done on 2026-04-12: installed k3s in a minimal profile with traefik, servicelb, local-storage, and network-policy disabled.
  • Done on 2026-04-12: validated core addons on sol; both coredns and metrics-server are healthy.
  • Done on 2026-04-12: prepared shared namespace trade-infra with ClusterIP services postgres-host and redis-host backed by host EndpointSlice targets on 149.50.96.162.
  • Done on 2026-04-12: opened ufw access on cni0 only for pod CIDR 10.42.0.0/24 to 6443, 10250, 5432, and 6379.
  • Done on 2026-04-12: validated pod -> service -> host connectivity from a test pod to both Postgres and Redis.

18. Install Postgres and Redis on mevnode

  • Done on 2026-04-12 for host-level bootstrap.
  • Bring up the data plane first: Postgres and Redis.
  • Validate persistence, storage placement, service discovery, restart behavior, and cold start.
  • Validate that Postgres lands on the dedicated 1 TiB trade storage area and that Redis lands on its separate small quota before application rollout.
  • Do not install application components until Postgres and Redis are healthy.
  • Done on 2026-04-12: Postgres and Redis are running on sol as host services, bound to 127.0.0.1 and 149.50.96.162 for k3s pod access.
  • Done on 2026-04-12: validated Postgres on /srv/trade/postgres/16/main, validated Redis on /srv/trade/redis, and confirmed btrfs quotas are active for both paths.
  • Done on 2026-04-12: Postgres listens with pod CIDR access in pg_hba.conf, and Redis announces 149.50.96.162 for cluster-aware clients inside k3s.
  • Done on 2026-04-12: installed TimescaleDB 2.26.2 packages on host Postgres for sol, enabled shared_preload_libraries=timescaledb, and provisioned application role/database admin/crypto matching the live trade-postgres secret from trade-staging.

19. Bootstrap an organization-scoped Gitea Actions runner on mevnode

  • Done on 2026-04-12.
  • Use trade-next/trade-gitops as the canonical bootstrap source, not an ad-hoc shell history on the host.
  • Scope the runner at the trade-next organization level so every migration repository can reuse the same execution plane.
  • Keep the first bootstrap simple: one runner replica on sol, one deployer service account, and one org secret carrying a kubeconfig for cluster access.
  • Keep the runner state persistent only where necessary; avoid long-lived Docker layer storage until image caching strategy is explicitly planned.
  • Done on 2026-04-12: created trade-next/trade-gitops initial main branch with bootstrap/gitea-actions manifests, scripts, and a smoke workflow.
  • Done on 2026-04-12: deployed trade-next-act-runner in namespace gitea-actions on sol using docker.io/gitea/act_runner:latest with a docker:27-dind sidecar.
  • Done on 2026-04-12: created trade-gitops-deployer service account and initial cluster-admin binding for first-pass GitOps bootstrap.
  • Done on 2026-04-12: synced K3S_KUBECONFIG_B64 as an organization secret in trade-next.
  • Done on 2026-04-12: verified the runner is online in Gitea with labels ubuntu-latest and k3s-deploy.
  • Done on 2026-04-12: verified workflow execution from trade-next/trade-gitops; commit c566978 completed with status success for runner-smoke / smoke (push).

20. Prepare a minimal canary namespace for trade on mevnode

  • Done on 2026-04-12.
  • Use a dedicated canary namespace for R001, not the default namespace and not the infra namespace.
  • Put namespace-level CPU, memory, object-count, and storage caps in place before the first application manifests are applied.
  • Keep the first canary envelope conservative until the validator protection budget is finalized.
  • Validate that the canary namespace can resolve and reach postgres-host.trade-infra.svc.cluster.local:5432 and redis-host.trade-infra.svc.cluster.local:6379.
  • Done on 2026-04-12: created trade-next/trade-gitops environment module at environments/sol/trade-r001-canary.
  • Done on 2026-04-12: applied namespace trade-r001-canary on sol with revision label R001 and canary environment labels.
  • Done on 2026-04-12: applied ResourceQuota in trade-r001-canary with caps requests.cpu=2, limits.cpu=6, requests.memory=4Gi, limits.memory=12Gi, pods=20, services=10, configmaps=20, secrets=30, persistentvolumeclaims=4, requests.storage=100Gi.
  • Done on 2026-04-12: applied LimitRange in trade-r001-canary with default request 100m/128Mi, default limit 1 CPU/1Gi, and per-container max 2 CPU/4Gi.
  • Done on 2026-04-12: verified deployment through Gitea Actions; commit 060dcc3 completed with status success for deploy-trade-r001-canary / apply (push).
  • Done on 2026-04-12: verified an in-cluster connectivity smoke test from trade-r001-canary to host-backed Postgres and Redis services.

21. Bring up Hasura, API, and frontend on mevnode

  • Done on 2026-04-12.
  • Bring up Hasura only after Postgres is healthy.
  • Bring up API and frontend only after Hasura, Postgres, and Redis are healthy.
  • Use trade-next/trade-gitops as the source of truth for the canary application surface, not ad-hoc manifests on the host.
  • Keep the first application rollout internal to the cluster: ClusterIP services and health checks first, public ingress later.
  • Reuse the live R001 application images and live application secrets, but point them at the target host Postgres on sol.
  • Done on 2026-04-12: added Hasura, trade-api, and trade-frontend manifests to trade-next/trade-gitops under environments/sol/trade-r001-canary.
  • Done on 2026-04-12: added operator scripts to trade-next/trade-gitops for sol host preparation, gitea-registry secret creation, and live secret sync from mevnode_bot/trade-staging into trade-r001-canary.
  • Done on 2026-04-12: prepared trade-r001-canary secrets on sol for trade-postgres, trade-hasura, trade-api, trade-frontend-tokens, trade-basic-auth, and gitea-registry.
  • Done on 2026-04-12: ran postgres-migrate and hasura-bootstrap jobs successfully on sol.
  • Done on 2026-04-12: deployed Hasura, trade-api, and trade-frontend to trade-r001-canary; all three deployments reached Available.
  • Done on 2026-04-12: verified internal HTTP health checks 200 for http://hasura:8080/healthz, http://trade-api:8787/healthz, and http://trade-frontend:8081/healthz.
  • Done on 2026-04-12: verified GitOps execution through Gitea Actions; commit 6672e10 completed with status success for deploy-trade-r001-canary / apply (push).

22. Migrate publishers and ingest only after storage and Redis validation pass

  • Done on 2026-04-12.
  • Substep A is now in place on sol: deploy trade-ingestor first in a schema-compatible canary mode and verify its secret wiring, rollout behavior, and Hasura connectivity.
  • Substep B is now functionally in place on sol: the live R001 DLOB hot-path and all-path writer chains and the dlob_hot_* plus dlob_all_* tables are reconstructed first, and the remaining step is to switch the canary ingestor from dlob_stats_latest to the exact live derived query path.
  • Done on 2026-04-12: extended trade-next/trade-gitops canary environment with trade-ingestor, synced trade-ingestor-tokens, and added trade-ingestor rollout checks to the deploy-trade-r001-canary workflow.
  • Done on 2026-04-12: manually validated trade-ingestor on sol; deployment reached Available, restart count stayed at 0, and startup logs confirmed HASURA_GRAPHQL_URL=http://hasura:8080/v1/graphql, markets SOL-PERP,PUMP-PERP, and mode dlob_stats_ticks.
  • Done on 2026-04-12: after push of commit 948c37c, the GitOps path on sol rolled a fresh trade-ingestor pod and it remained healthy with restart count 0.
  • Done on 2026-04-12: added environments/sol/trade-infra to trade-next/trade-gitops with host-backed postgres-host, redis-host, agave-rpc-host, agave-ws-host, and agave-grpc-host services so canary workloads can consume the shared host services through Kubernetes DNS.
  • Done on 2026-04-12: installed host-side systemd socket proxies and ufw rules on sol so pods in k3s can reach Agave RPC on 8899, WebSocket on 8900, and Yellowstone gRPC on 10000.
  • Done on 2026-04-12: created the trade-dlob-rpc secret on sol from the live host Geyser token and wired the canary namespace to the host-backed Agave endpoints without hardcoding the token in Git.
  • Done on 2026-04-12: added dlob-redis, dlob-publisher-hot, dlob-hot-redis-to-postgres-raw-writer, and dlob-hot-postgres-to-postgres-derived-writer to trade-r001-canary in GitOps.
  • Done on 2026-04-12: reran postgres-migrate and hasura-bootstrap with additive dlob_hot_* schema and Hasura metadata on sol.
  • Done on 2026-04-12: manually validated the DLOB hot-path on sol; the raw writer persisted dlob_hot_snapshot_*, the derived writer persisted dlob_hot_derived_*, and dlob_hot_derived_latest contained current rows for markets 0, 20, and 72.
  • Done on 2026-04-12: added dlob-publisher-all and dlob-all-redis-to-postgres-derived-writer to trade-r001-canary in GitOps and validated that both deployments reached Available on sol.
  • Done on 2026-04-12: tuned the new dlob-publisher-all and dlob-all-redis-to-postgres-derived-writer manifests to fit the namespace guardrails by setting limits.cpu=500m and RollingUpdate with maxSurge=0, maxUnavailable=1, which removed the ResourceQuota rollout deadlock at limits.cpu=6.
  • Done on 2026-04-12: manually validated the DLOB all-path on sol; dlob_all_derived_latest and dlob_all_derived_ts were populated and the new publisher and writer stayed healthy after rollout.
  • Done on 2026-04-12: switched the canary trade-ingestor to the exact live derived query path; after rollout on sol, fresh drift_ticks rows showed raw.from = dlob_hot_derived_latest for SOL-PERP and raw.from = dlob_all_derived_latest for PUMP-PERP.
  • Done on 2026-04-12: added api-token-seed bootstrap logic for trade-frontend-tokens/read.json, which inserted the matching hash into api_tokens on sol and fixed trade-api auth for the frontend read token.
  • Done on 2026-04-12: validated the application surface against the reconstructed derived tables; trade-api /v1/ticks returned fresh SOL-PERP and PUMP-PERP ticks, trade-api /v1/chart returned SOL-PERP candles, and trade-frontend returned 200.

23. Validate host health, agave health, trade health, and end-to-end flow after rollout

  • In progress.
  • Initial validation on 2026-04-12: after the DLOB hot/all-path rollout, sampled Agave slot lag on sol at 0 versus https://api.mainnet-beta.solana.com, with local health still reporting ok.

24. Keep mevnode_bot as a rollback target until the new stack is stable

  • Pending.

Chapter 3

    1. Define hard database and cache constraints.
    1. Reconstruct the current live mevnode_bot and trade-staging state into canonical Git/IaC in a new Gitea organization.
    1. Fix dlob-publisher-hot startup, readiness, and liveness.
    1. Fix dlob-publisher-all startup, readiness, and liveness.
    1. Confirm whether trade Redis is meant to run as a single instance or as Redis Cluster.
    1. Align publisher Redis client mode with the actual deployed Redis topology.
    1. Restore or recreate the missing gitea-registry image pull secret.
    1. Verify that image pulls work after node reboot and on a cold start.
    1. Measure the real PostgreSQL data size inside the current trade PVC.
    1. Explain why the declared 20Gi PVC currently consumes about 585 GiB on disk.
    1. Decide which trade datasets must be migrated and which can be rebuilt.
    1. Define a dedicated storage path or device for trade data on mevnode.
    1. Define hard storage quotas and monitoring for trade data on mevnode.
    1. Define CPU and memory reservations that protect agave-validator.
    1. Define the minimum safe free RAM headroom on mevnode during rollout.
    1. Define the maximum acceptable swap usage on mevnode during rollout.
    1. Install and bootstrap k3s on mevnode.
    1. Install Postgres and Redis on mevnode.
    1. Bootstrap an organization-scoped Gitea Actions runner on mevnode.
    1. Prepare a minimal canary namespace for trade on mevnode.
    1. Bring up Hasura, API, and frontend on mevnode.
    1. Migrate publishers and ingest only after storage and Redis validation pass.
    1. Validate host health, agave health, trade health, and end-to-end flow after rollout.
    1. Keep mevnode_bot as a rollback target until the new stack is stable.