Skip to content
Docs / StateMirror
DOCUMENT / STATEMIRROR

Running StateMirror Core in production

This guide covers operating the available Apache-2.0 Core. The planned StateMirror Production offering is not yet available.

Core supplies the evidence ledger. Your team supplies the operating environment and decides whether its failure behavior and trust model fit the application.

Implementation baseline: Core v1.0.0. The repository declares Node.js ≥20; its example containers use Node 20 Alpine and PostgreSQL 16 Alpine. These defaults are not a compatibility or maintenance commitment. Review the exact release you deploy; paid artifact versions are a separate line.

Go to the printable readiness checklist →

TYPE
Operator manual

Ownership

#
Who owns what
OwnerResponsibilityBoundary
StateMirrorAccept submitted evidence; assign receipts and sequence; retrieve; verify payload and chain integrity.Does not discover inputs, decide, enforce or verify external truth.
OperatorDeploy the service; secure PostgreSQL and transport; manage secrets, backups, retention, monitoring and upgrades.Accept the privileged database trust boundary and test recovery.
ApplicationChoose the decision and consulted facts; minimize the payload; submit, retry and retain the evidence reference.Own decisions, actions, payload meaning and behavior when capture fails.

Runtime and deployment

#

The supplied entry point starts a Node process, connects to PostgreSQL and listens over HTTP on 0.0.0.0, port 8080 by default. It closes the server and connection pool on SIGINT or SIGTERM. Operators provide process supervision, restart policy and deployment isolation.

The Dockerfile builds TypeScript and runs as a non-root user. The Compose file is a local example: it publishes PostgreSQL and HTTP ports and contains demo credentials. Review network exposure and credentials before adapting it for a shared environment.

Process entry point · Dockerfile · Compose example

Database and migrations

#

Provide PostgreSQL with durable storage. Each service process creates a pool with at most 20 connections, a 5-second connection timeout and a 30-second idle timeout. Budget database connections across all processes; Core does not provision replication or failover.

Run npm run migrate from the source checkout in one controlled deployment step before starting the service. The runner applies pending SQL files in filename order, transactionally per migration, and records them in schema_migrations. It does not provide a concurrent migration coordinator or down-migration command.

The supplied runtime image omits development dependencies, including the tsx used by the npm migration script. Run migrations from a prepared source/build environment with the release's files and credentials. The image also contains dist/db/migrate.js and the SQL files; validate your chosen invocation before deployment.

Pool configuration · Migration runner

Network, credentials and secrets

#

Core does not terminate TLS. Operators supply secure ingress, database connection security, network isolation, disk/backup encryption and secret storage. Restrict the public health route, which exposes ledger progress.

WRITE_API_KEYS authorizes snapshot creation; reads and verification accept READ_API_KEYS or write keys. These are instance-wide service credentials. They do not isolate customers or authenticate end users. Keys are loaded at startup; plan configuration changes and restarts when rotating them.

The CLI accesses PostgreSQL directly through DATABASE_URL, bypassing HTTP API-key checks. Protect that path separately. Replace all example passwords and keys. Keep secrets and full payment details out of evidence and support reports.

Full security and integrity review → · Authentication implementation

Backups, restore and retention

#

Back up snapshots, idempotency_keys, schema_migrations and the database metadata needed to restore them. Define recovery time and acceptable data loss with the application team.

Restore into an isolated environment. Check schema history, expected latest sequence and receipt timestamp, then verify representative ranges. Compare progress against records retained outside the restored database. A consistent older backup can verify successfully while omitting later evidence.

Core has no evidence-retention scheduler or snapshot delete API. Operators define retention and review its privacy and integrity implications. Deleting old rows can break links or remove required predecessors; a verification pass does not establish that the expected final records exist.

CLEANUP_ON_STARTUP=true deletes expired idempotency records at startup only. Creation assigns a 24-hour expiry; lookup does not itself filter expired records. This is retry housekeeping, not evidence retention. After cleanup, reusing an old key can create another snapshot.

Health and monitoring

#

GET /v1/health queries PostgreSQL and returns status, database, latest_sequence and latest_received_at. It can return HTTP 200 with status: unhealthy and database: disconnected. Check the body, not only the status code.

Core supplies request/error logging through Fastify/Pino. No dedicated metrics endpoint, alerting service or dashboard is registered. Operators collect logs and monitor health, application capture failures, database capacity, backup results and deployment health.

Health response behavior · Server and logging configuration

Upgrades and rollback

#
  1. Pin the intended release and inspect its change history and migration files.
  2. Back up the database and rehearse the upgrade against a restored copy.
  3. Coordinate writers and migration execution; deploy with explicit configuration.
  4. Check health response fields, a new submission and representative integrity ranges.
  5. Retain the prior artifact and a tested restoration procedure.

Changing the running binary does not undo database changes. There is no automatic rollback facility. Decide whether rollback requires restoring a backup, including how to reconcile evidence written after that backup. Applications own payload-shape compatibility.

APP_VERSION is a configured response label, not proof of deployed source identity. Record the actual release/commit alongside it. The website's SITE BUILD label describes this website, not Core.

Failure modes and retries

#
Failures to rehearse in your environment
ConditionCurrent behaviorYour response
PostgreSQL unavailableStartup connection failure exits the process. Runtime failures can produce 500 or 503 responses depending on the failing path.Monitor the body/errors; choose application behavior during missing capture.
Lost response or timeoutA write may have committed before the caller lost the response.Retry the identical submission with the same key; retain the returned snapshot ID.
Idempotency reuseMatching payload hash replays the receipt; a different payload returns 409. Envelope fields are not part of that comparison. Concurrent first attempts can conflict.Keep the full retry envelope unchanged. Review conflicts and cleanup timing; do not assume indefinite deduplication.
Malformed or oversized inputValidated field failures return 400; the canonical payload size check returns 413. Earlier parser or unhandled shape failures can follow the global 500 handler.Validate submissions, inspect the response and correct the request before retrying.
Verification failureA verification response can be HTTP 200 with valid: false and failure details.Preserve the failed result, inspect the reported sequence and investigate storage/access changes. Do not silently rewrite evidence.
Missing snapshotRetrieval by a valid but absent snapshot ID returns 404.Check the saved reference and recovery history; absence does not establish whether the application acted.

Core does not supply a durable application retry queue, cross-system transaction or capture-outage policy. Its default canonical payload limit is 1,048,576 bytes; the HTTP request-body limit also applies to the full envelope. Validate practical limits with your deployed version.

Integrity trust model

#

Verification recomputes the canonical payload hash, chain hash and applicable links and sequence continuity. The hash covers state_payload, not every envelope field. Verification does not establish upstream truth, decision correctness or successful side effects.

Core's migration installs a trigger rejecting ordinary snapshot UPDATE and DELETE operations. A privileged database administrator able to bypass those controls, rewrite records and recompute hashes remains inside the trust boundary. Stored hashes cannot detect every consistent rewrite or chain-suffix deletion. Core has no independent checkpoint or anchoring facility.

Inspect the trust-boundary diagram → · Verification semantics →

Capacity and performance

#

Snapshot transactions take a shared PostgreSQL advisory lock while assigning the next sequence and writing the linked record. Adding service processes does not remove this serialized write section. Range verification fetches the requested records into memory; use deliberate range sizes.

No throughput or latency target is established here. Measure your payload sizes, write concurrency, retrieval mix, verification ranges and database latency. Record hardware, runtime, PostgreSQL configuration, release, errors and repeated-run variation before using results for capacity planning.

Write transaction · Range verification

Production readiness checklist

#

Use this as a deployment review record. Checks stay in this page session; print a copy for your review. A checked box records your assessment, not a certification.

Deployment
Security
Operations
Application
Integrity and upgrades

Use your browser's Print command to keep this guide and checklist. For deployment questions or product feedback, discuss StateMirror. Review is best effort and does not include operating your deployment.