Single Node
A single ScramDB node runs the full UTAP engine on one machine. One node handles your transactional writes and your analytical queries against the same live copy of the data, with no separate warehouse and no data pipeline to keep in sync. This is the simplest way to run ScramDB, and it is a real production option whenever your workload fits comfortably on one server. It is also unrestricted on every edition, including Community.
Everything on this page uses exactly the same engine you would run in a cluster. If you later need high availability or more capacity, you move to a distributed cluster (which requires an Enterprise license) without changing your SQL or your application.
Local and developmentβ
The fastest way to get a node running is Docker:
docker run -d \
--name scramdb \
-p 5432:5432 \
-v scramdb-data:/var/lib/scramdb \
scramdb/scramdb:latest
Connect with psql or any PostgreSQL client or driver:
psql "host=127.0.0.1 port=5432 user=scramdb dbname=scramdb"
ScramDB speaks the PostgreSQL wire protocol, so psql, JDBC, psycopg, and the standard drivers all work unchanged. See the Docker guide for volumes and health checks.
The container starts with --pg-no-auth, which trusts every connection with no password. This is fine for local development on a machine or network you trust. Before running the image anywhere reachable by anyone else, see Securing a node.
Production single-nodeβ
A single node is production-ready. To run one durably:
-
Persist the data directory. Mount a volume at
/var/lib/scramdb(shown above). This holds the columnar storage and the write-ahead log, so your data survives restarts and upgrades. The shipped image also archives the write-ahead log to a subdirectory of that same volume by default, which is what point-in-time recovery reads from; see Backup and restore. -
Turn authentication on. Drop
--pg-no-authfrom the container command, or setpg_no_auth = false(the engine default) in your own config and don't pass the flag. See Securing a node. -
Use fast local storage. Put the data directory on an NVMe SSD. ScramDB writes the log on the commit path, so storage latency is what commit latency follows.
-
Expose metrics. Publish port
9090to scrape Prometheus metrics from/metrics, and to reach the plain/healthendpoint:docker run -d \--name scramdb \-p 5432:5432 \-p 9090:9090 \-v scramdb-data:/var/lib/scramdb \scramdb/scramdb:latest -
Size the machine to the workload. See the section below and the requirements page.
Durability, crash recovery, and the full set of PostgreSQL-compatible isolation levels (Read Committed, Repeatable Read, and Serializable) are all present on a single node. They are the same guarantees a cluster provides, just without replication across machines.
Sizing basicsβ
ScramDB scales with the machine it runs on. Three resources matter:
- CPU cores. ScramDB spawns one worker thread per core in its resolved pool, sized from the container or OS CPU limit rather than just the visible core count, and runs each query in parallel across those workers. See Parallelism for exactly how that pool is sized.
- Memory. ScramDB uses memory for its buffer pool, for query execution (joins, sorts, and aggregation), and for the JIT compiler. Size the buffer pool and execution memory with the percent-based keys (they auto-size from detected or cgroup-limited RAM) or pin exact byte values in the configuration file, and leave headroom for the operating system.
- Storage. An NVMe SSD is strongly recommended. ScramDB defaults to direct I/O for its columnar storage, bypassing the OS page cache, and analytical scans reward fast sequential throughput.
See Requirements for hardware guidance.
Configurationβ
A node is configured with a TOML file passed on the command line with -c (default scramdb-config.toml in the working directory if you omit the flag). The container image ships a working single-node configuration, so you do not need one to get started. When you do want to tune a node, mount your own file. The keys below are the common ones:
[general]
# Listen for PostgreSQL clients. The engine's own default is loopback-only
# (127.0.0.1:5432); the published Docker image's startup command overrides
# this to 0.0.0.0:5432 so the container is reachable from outside itself.
pg_address = "0.0.0.0:5432"
# Serve Prometheus metrics and /health on 9090 (set to 0 to disable).
metrics_port = 9090
# Compile hot queries to native code (default true).
jit_enabled = true
[storage]
# Instance identity (both required).
prod_name = "tundra"
shard_id = 0
# Where the columnar data and write-ahead log live.
basedir = "/var/lib/scramdb"
# Buffer pool and per-query execution memory, as a share of available RAM.
buffer_pool_percent = 60
execution_memory_percent = 15
[storage] is the only section with no default of its own: prod_name, shard_id, and basedir are always required, plus one of buffer_pool_percent or buffer_pool_size_bytes to size the buffer pool. Every other section, including [general], is optional; an omitted field keeps its default.
An unrecognized top-level key in the file is a hard parse error, not a silently ignored typo: ScramDB refuses to start rather than run with a config it can't fully account for. See Configuration for the full section reference.
The absence of a [cluster] section is what makes this a single node. Adding one turns on clustering (Enterprise license required); nothing else about the node changes.
Log verbosity is controlled by the SCRAMDB_LOG environment variable (off, trace, debug, info, warn, or error; default info), and log format by SCRAMDB_LOG_FORMAT. All other tuning lives in the configuration file, not in environment variables.
Shutting down cleanlyβ
ScramDB handles SIGTERM and SIGINT by draining in place: it stops accepting new connections, waits for active queries to finish (up to shutdown_drain_timeout_secs, default 10 seconds, under [general]), then quiesces the JIT background worker (up to shutdown_jit_quiesce_timeout_secs, also default 10) before flushing storage and the write-ahead log. If you run under docker stop -t <seconds> or a Kubernetes terminationGracePeriodSeconds, set that grace period to at least the sum of both timeouts so ScramDB gets to finish its own drain instead of being killed mid-shutdown.
When to move to a clusterβ
A single node is the right choice until you need one of these:
- High availability: you want the database to keep serving when a machine fails.
- More capacity than one machine holds: your data or your query load outgrows a single box.
Both are covered by a distributed cluster, which runs this same engine across several nodes and presents one consistent, serializable database. Clustering requires an Enterprise (or Trial) license; a Community node with a [cluster] section configured will not start.