Copy-on-Write¶
Mechanics: fork() marks all shared parent/child pages read-only. First write to a shared page → minor fault → kernel copies that page → both processes get private writable copies. Only written pages are copied. fork() cost = O(page table size), not O(data size).
RDB snapshots: Redis calls fork(). Child inherits the full dataset view at zero copy cost. Parent continues writes, triggering CoW on modified pages. Child serializes snapshot to disk. Peak memory = dataset + pages modified during snapshot. For write-heavy workloads, this can temporarily double memory.
Go GC: doesn't use fork(). Concurrent tricolor mark-and-sweep with write barriers runs alongside the application.
Common pitfall¶
Assuming a fork()-based snapshot (like Redis's RDB) is "free" because
fork() itself is cheap ignores what happens after — a write-heavy
parent process triggers CoW on every modified page during the
snapshot window, and for a workload with a high write rate touching a
large fraction of memory, peak memory usage can approach double
the dataset size for the snapshot's duration, exactly as the RDB
example above notes. Provisioning RAM based only on steady-state usage,
without accounting for this transient doubling during snapshots, is
how a snapshot operation itself triggers an OOM kill.