jonnify·redis /redis-patterns/production-operations/kernel-tuning/persistence-safe-settings

R8.01.3 · Kernel tuning — dive 3

Durable on a crash, never silently losing work.

A job store has two quiet ways to lose work: it crashes and discards the writes it acknowledged, or it fills up and evicts the keys it was holding. These settings close both gaps — the store fails loudly instead of quietly.

Grounding: infra/valkey/conf/valkey.conf (the persistence, memory, and network blocks, verbatim) · bcs.8.md B8.2 (the one-second loss bound, reject-don’t-evict) · the source kernel-tuning guide (the listen-queue and file-descriptor figures).

Pick a production risk — read the setting that prevents it. Select a risk to light its path to the setting; the readout names the guarantee.
lost work on a crash appendfsync everysec≈ 1s loss bound silent eviction noevictionreject, don’t evict a SIGTERM mid-write shutdown-timeout 10flush the log first a connection burst tcp-backlog + somaxconnaccept, don’t drop
readout · Select a production risk. Each one maps to a single setting in the real valkey.conf (or a host sysctl beside it) that turns a quiet failure into a loud one.

Static map — a crash → appendfsync everysec (loss ≈ 1s) · a full store → noeviction (a rejected write, not a dropped key) · a SIGTERM → shutdown-timeout 10 (the log flushes) · a burst → a raised tcp-backlog/somaxconn (the connection is accepted).

§1

The append-only log and the loss bound

valkey.conf · persistence block

The first question of durability is one number: after a crash, how much acknowledged work is gone. With an append-only log turned on and an fsync cadence of once a second, the answer is bounded and small.

appendonly yes makes the volume hold an append-only file — every write that changes the keyspace is appended to a log on disk. appendfsync everysec flushes that log to the disk once a second on a background thread. The manuscript states the bound directly: “with appendonly on and appendfsync everysec, the volume holds an append-only log and the loss bound after a crash is roughly one second of writes, not a whole snapshot interval.” A snapshot-only store loses everything written since the last snapshot — minutes of work; the append-only log narrows that window to about one second.

aof-use-rdb-preamble yes lets the periodic rewrite start from a compact binary preamble rather than replaying every command, so the rewrite is fast and the file stays small. save "" turns snapshotting off on purpose: with the append-only file as the single source of durability, there is no reason to keep a second snapshot fork competing for the machine. One fork source, one durability mechanism. The copy-on-write spike of that one rewrite fork is dive 1’s subject, not repeated here.

infra/valkey/conf/valkey.conf · AOF is the single source of durabilityfrozen
# ---- Persistence: AOF is the single source of durability ----
# One fork source. AOF everysec bounds worst-case loss to about one second.
appendonly yes
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-use-rdb-preamble yes
save ""                          ← RDB off: it does not compete for a second fork

Notes on ValkeyThe append-only file is replayed at startup to rebuild the in-memory dataset; appendfsync everysec is the balance Valkey recommends — durability close to always at a fraction of its fsync cost — valkey.io/topics/persistence.

An append-only log with a once-a-second fsync turns “how much did the crash cost” from an open question into a bound: about one second of writes, never a whole snapshot interval.

§2

Reject, do not evict

valkey.conf · the memory guardrail

The second way a job store loses work is memory pressure. When a store fills up it must choose: throw old keys away to make room, or refuse the new write. For a cache the first is fine — an evicted key is only a future miss. For a queue it is a silent data-loss bug.

maxmemory 512mb is a loud guardrail, not a working ceiling — the live dataset is single-digit megabytes, so 512 sits far above it and leaves the rest of the box for fork copy-on-write and client buffers. maxmemory-policy noeviction is the load-bearing line. The config’s own comment names the trade: “noeviction means a runaway keyspace REJECTS writes loudly instead of being OOM-killed silently.” The manuscript states the principle: “a queue that silently drops keys is a queue that silently loses work, so memory pressure must surface as write errors and alerts.” Under noeviction, a write that would exceed maxmemory returns an error to the caller — a signal to alert on — rather than discarding a job that something already enqueued.

maxmemory-clients 64mb caps the memory a single client’s buffers may hold, so one slow or stuck consumer cannot drive the whole instance into that pressure on its own.

infra/valkey/conf/valkey.conf · a loud guardrail, not a working ceilingfrozen
# ---- Memory: a loud guardrail, not a working ceiling ----
# noeviction means a runaway keyspace REJECTS writes loudly
# instead of being OOM-killed silently.
maxmemory 512mb
maxmemory-policy noeviction
maxmemory-clients 64mb

Notes on ValkeyThe eviction policies (the allkeys-lru family and the rest) decide what to drop when a write would exceed maxmemory; noeviction is the one policy that drops nothing and returns an error instead — valkey.io/topics/lru-cache.

For a cache, eviction is a feature; for a job store it is data loss. noeviction makes memory pressure a rejected write and an alert, not a key that quietly disappears.

§3

Fail loudly

valkey.conf · the network/shutdown block

Rejecting writes under memory pressure is one half of failing loudly. The other half is refusing to acknowledge data the store cannot promise to keep, and giving the log a chance to flush on the way down.

propagation-error-behavior panic is the strictest possible posture, and the config states why in one line: “fail the write rather than acknowledge data that may not survive.” If a write cannot be propagated where it must go, the server fails the write rather than returning a success the data does not back. A false acknowledgement is worse than a visible error — the caller that hears “OK” stops worrying about the job; an error makes it retry.

shutdown-timeout 10 covers the orderly exit. On a SIGTERM — the signal a deploy or a platform sends to stop the process — the server is given ten seconds to flush the append-only file before the platform forces it down. The config’s comment: “give the AOF a chance to flush on SIGTERM.” Without that window, a rolling deploy could discard the last unflushed second on every restart.

# valkey.conf — fail loudly rather than acknowledge un-survivable data.
propagation-error-behavior panic   # fail the write, never a false OK
shutdown-timeout 10                 # flush the AOF on SIGTERM before forced exit

A store that returns a success it cannot back is the worst kind of quiet failure. panic refuses the false acknowledgement; shutdown-timeout 10 keeps a deploy from eating the last unflushed second.

§4

Staying connected

kernel-tuning.md.txt · TCP stack & file descriptors

A dropped connection is dropped work, so the network settings take the same posture as the persistence ones: accept the burst rather than drop it. These are the connection-survival half of the source’s kernel-tuning guide.

tcp-backlog sets the listen queue for incoming connections. The source’s kernel-tuning guide warns that the Linux default is 128, so during a traffic spike new connections are dropped before the server ever sees them. The effective backlog is min(tcp-backlog, somaxconn) — both the application’s tcp-backlog and the kernel’s net.core.somaxconn must be raised, or whichever is smaller caps the queue. tcp-backlog lives in valkey.conf; somaxconn and the other knobs are kernel settings, set on the host:

# /etc/sysctl.conf — the KERNEL half of the connection-survival pair
net.core.somaxconn=65536            # raise the kernel's accept queue to match
net.ipv4.tcp_max_syn_backlog=65536

# systemd unit — the file-descriptor ceiling; each connection costs one fd
LimitNOFILE=65536

The source sets somaxconn to 65536 so the kernel’s queue is never the limit, and raises the file-descriptor ceiling to 65536 because each connection consumes one file descriptor and a server’s maxclients is bounded by the descriptors available to it. Back in valkey.conf, tcp-keepalive 300 sends a keepalive every 300 seconds so a load balancer or firewall does not silently reap a long-lived idle connection, and the pub/sub output buffer is bounded so a slow subscriber is dropped rather than allowed to grow the server’s memory without limit.

infra/valkey/conf/valkey.conf · the network and shutdown surfacefrozen
# ---- Network ----
port 6390
tcp-backlog 511                  ← effective = min(tcp-backlog, somaxconn)
tcp-keepalive 300
# ---- Client output buffers ----
# A slow subscriber is dropped rather than growing memory without limit.
client-output-buffer-limit pubsub 32mb 8mb 60

Notes on ValkeyBoth ends of the listen queue have to be raised together — the server’s tcp-backlog and the kernel’s somaxconn; whichever is smaller wins, which is why a high tcp-backlog alone does nothing on a stock host — valkey.io/topics/admin.

the pattern

A durable store fails loudly: bound crash loss with an append-only log, reject writes on memory pressure rather than evict, refuse un-survivable acknowledgements, and accept a connection burst rather than drop it.

its EchoMQ application

The real valkey.conf fronts the codemojex queue’s emq:{q}: keyspace with appendfsync everysec + noeviction + panic, and the host raises somaxconn/LimitNOFILE to 65536.

the application · the queue’s store, configured to refuse

Why a job store chooses this engine

EchoMQ keeps its jobs in the braced emq:{q}: keyspace on this exact Valkey. The manuscript frames the durability choice for the queue in one passage:

bcs.8.md · B8.2 · Valkey on a Fly machinefrozen
noeviction              ← a queue that drops keys loses work
appendfsync everysec    ≈ 1s  loss bound after a crash
backlog + fd limits     ← a burst of clients is accepted, not dropped

The EchoMQ protocol depth — the lane consumers, the leases, the Lua — is the dedicated /echomq course; this page stays on the settings.

Same posture, three layers: the log bounds the loss, noeviction and panic refuse to lose or fake work, and the raised backlog and descriptor ceiling keep a burst of clients from being dropped at the door.

§5

Beneath the volatile tier

bcs.5.md · the persistence floor

The settings above bound the queue’s crash loss to about one second. That is the right floor for a volatile work tier, but it is not the whole durability story. Deep history and off-box durability live one tier down, on the persistence floor: when the bus trims a stream, EchoStore.StreamArchive folds the trimmed segments into EchoStore.Graft’s append-only CubDB at a reserved high page range, and a streamer ships those pages on to Tigris object storage — deep history without resident memory. The volatile tier keeps the last second; the durable floor keeps everything, addressable beside the live tail.

the door · the durability dial, one tier down

The persistence floor

That floor is its own surface — the durability dial from ETS to Valkey to CubDB and on to Tigris. The /echo-persistence course carries it; this page stays on the volatile tier’s valkey.conf.

The queue’s Valkey bounds loss to about a second; the persistence floor beneath it keeps the rest, off-box and addressable — two tiers, one durability dial.

§6

Recap — fail loudly

return → R8 · Production & Operations

A durable job store is one that fails loudly. The append-only log with appendfsync everysec bounds crash loss to about a second; noeviction makes memory pressure a rejected write and an alert instead of a silently dropped key; propagation-error-behavior panic refuses to acknowledge data that may not survive; shutdown-timeout 10 flushes the log on the way down; and a raised tcp-backlog/somaxconn pair and file-descriptor ceiling accept a connection burst rather than drop it. Every one of these settings is in the real valkey.conf (or the host sysctls beside it) that fronts the codemojex queue. This is the last dive of the module — the recap returns to the chapter.

§7

References

sources · related

Sources

  • Valkey — Persistence — the append-only file and the everysec posture; a roughly one-second loss bound after a crash.
  • Valkey — SHUTDOWN — the orderly stop that shutdown-timeout bounds, flushing the append-only file on SIGTERM.
  • Redis — Persistence — RDB and AOF, the fsync policies, and the durability trade the append-only file makes.
  • Redis — Documentation — the production guidance: overcommit, the listen backlog, file-descriptor limits, and the startup warnings.
  • Valkey — Administration — the listen-queue and file-descriptor figures: the 128 default, somaxconn 65536, and LimitNOFILE 65536.

Related in this course