The full picture
- Why it exists: one shared memory controller became the bottleneck as core counts grew — distributing memory with the sockets restored bandwidth at the price of uniformity. (Chiplet CPUs — EPYC's CCDs — bring mild NUMA-ness inside a single socket now.)
- First-touch is the policy to know: memory is placed on the node of the thread that first touches it — so an init thread that pre-touches the whole heap puts it all on one node, and worker threads elsewhere pay remote latency forever. This interacts directly with
-XX:+AlwaysPreTouchand explains 'why is half my pool slower'. - Database lore is NUMA lore: MySQL's historical swap-despite-free-memory (one node full, allocator refusing remote) →
numa_interleave; Redis/nginx per-socket instances; JVM-XX:+UseNUMAmaking Parallel/G1 allocate young gen locally. - The architect decision pattern: either embrace (shard: one process per node, pin threads+memory, network-shard between them — the low-variance choice) or interleave (spread pages round-robin: uniform mediocrity, no cliffs — right for one big cache). What's wrong is pretending the machine is uniform.
- Kubernetes angle: Topology Manager + CPU Manager static policy align container CPUs and memory to a node for the pods that ask — the 'Guaranteed QoS' story extends to NUMA.