Local Durability
Use --data-dir to save a node’s resident effects to disk and restore them after a restart. Without it, Swytch runs in
memory only.
Local durability mirrors the effects Swytch currently retains, including effects received from peers. When the memory governor releases an effect, its disk record is released too. This is for restarting a node, not keeping a complete backup.
Need history that survives local eviction or losing a node’s disk? Use Swytch Cloud. It retains acknowledged effects independently of the node’s local cache and works alongside self-hosted Swytch.
For Redis:
swytch redis --bind 127.0.0.1 --maxmemory 256mb --data-dir ./swytch-data
For SQL:
swytch sql --listen 127.0.0.1:5433 --maxmemory 256mb --data-dir ./swytch-sql-data
Swytch creates the directory if it doesn’t exist. The process needs permission to create, write, and remove files. Give each node its own directory; Swytch locks the directory to prevent another process from writing to it.
Use the same path on subsequent starts. If you omit --data-dir, Swytch starts in memory-only mode and doesn’t load the
existing files. An absolute path avoids surprises when running under a service manager. Check swytch redis --help or
swytch sql --help if your installed version doesn’t recognize the flag.
With the Redis server running, open another terminal:
redis-cli SET durability:example restored
redis-cli GET durability:example
Stop the server with Ctrl+C, restart it using the same --data-dir, then run the GET again. The value should still be
restored.
Mount a persistent volume at the data directory:
docker volume create swytch-data
docker run --rm --name swytch-durable \
-p 127.0.0.1:6379:6379 \
--mount type=volume,source=swytch-data,target=/data \
ghcr.io/swytchdb/swytch:latest \
redis --bind 0.0.0.0 --maxmemory 256mb --data-dir /data
Stop it with docker stop swytch-durable. The named volume survives removal of the container and can be used by its
replacement. Pin an image version in deployments. A volume on the same host does not protect against loss of that host
or disk.
Effects are published without waiting for an fsync. The first unsynced write to a file schedules a sync within 10 ms;
later writes join that batch without extending its deadline. Files sync independently, and writes arriving during a sync
are included in a later batch. Clean shutdown flushes pending records.
A successful Redis reply is not confirmation that the effect has been synced to disk. A crash can lose recent writes. The 10 ms target can be exceeded because of scheduling, storage latency, or errors, and there is no Redis command to wait for the local mirror to finish syncing.
Local durability doesn’t change transaction binding or the meaning of EXEC. The DAG and existing reconstruction rules
still determine visible values. See transaction conflicts.
On startup, Swytch restores saved effects to the vertex pool and key index before accepting client traffic. Recovery
runs in parallel across files, using the available Go execution threads (GOMAXPROCS, or --threads for the Redis
server).
Effect identities are preserved, including the original identities of effects received from peers. The recovering node starts a new incarnation. Transaction binds restore their associated keys, and normal reconstruction determines the resulting values.
Look for durability recovery complete in the logs, along with the restored effect and key counts.
Recovery needs enough memory to restore the saved effects. If recovery would require evicting effects, Swytch cancels it and logs:
not enough free memory to recover state, please restart with more memory. Deleting storage and continuing in 30s
You have 30 seconds to stop the process and preserve the mirror. Stop any supervisor that would immediately restart it
with the same limits, increase the available memory or --maxmemory, then restart with the same data directory.
If the process remains running after the warning, Swytch deletes the local mirror and starts empty. Other peers or Swytch Cloud can supply effects they still retain, but neither can recover history it doesn’t have. On a standalone node, this may remove the only saved copy.
Allow memory for decoded effects, the key index, table-of-contents structures, mapped pages, and temporary recovery work. The on-disk size isn’t a reliable estimate of recovery memory. See sizing.
An unreadable or locked directory, unsupported format, or corrupt published record fails startup without invoking the low-memory deletion fallback. Preserve the directory while investigating.
Background sync failures are logged and retried. Storage-operation errors are returned where possible. Monitor disk space and durability logs; an earlier successful command doesn’t prove a later sync succeeded.
The disk mirror follows the memory governor. When an effect is no longer referenced, Swytch removes its table-of-contents entry. Other keys may still reference the same effect, in which case it remains available.
On Linux, Swytch releases allocated blocks with hole punching when the filesystem supports it. Other systems may leave freed space allocated until files become empty. Empty files are removed after active readers and writers finish.
Effects occupy whole filesystem blocks, so disk use can exceed their serialized size. Files append data, which means
their reported length can grow even when physical space has been released. Measure allocated disk usage rather than
relying only on file lengths. FLUSHALL clears both the in-memory state and its local mirror.
Files are grouped by originating node, with up to 64 buckets per origin:
swytch-data/
.swytch.lock
<originating-node-id>/
0.swytch
1.swytch
...
63.swytch
The bucket is selected by effect offset modulo 64. Each file contains a header, table of contents, and effect data; a file can contain effects for many application keys. Don’t edit or move individual bucket files.
To make a consistent copy, stop the node cleanly and copy the whole directory. Restore it with a compatible Swytch version and enough memory. Copying files while Swytch is running is not a supported backup method. This isn’t Redis RDB or AOF, and Redis persistence settings don’t control it.
Each node can use its own --data-dir, whether running alone or in a cluster. Configure peer discovery normally;
see joining a cluster. A node’s mirror contains its own resident effects,
not necessarily every key in the cluster.
For recoverable history beyond the local cache, use --cloud alongside --data-dir. Local disk sync and Cloud upload
acknowledgement are separate. A locally synced effect may not yet be acknowledged by Cloud, and a successful Redis
command doesn’t guarantee either. See Cloud durability semantics.
Go applications can configure local durability directly:
engine, err := effects.OpenEngine(ctx, effects.EngineConfig{
DataDir: "/var/lib/swytch",
MemoryLimit: 256 << 20,
})
Handle startup errors and close the engine cleanly to flush pending writes. beacon.RuntimeConfig.DataDir provides the
same setting for clustered runtimes. For deployment-specific configuration, see the Caddy
and Kubernetes guides.