systemd MemoryDenyWriteExecute breaks Node V8
Running a Node/TypeScript service under systemd with the standard hardening flags, on an ARM Linux host.
MemoryDenyWriteExecute=yes is a great default for Go binaries and other AOT-compiled services, and it propagates by copy-paste into systemd units across a deploy. But any V8-based runtime — Node, Deno, Bun — needs W+X pages for the JIT. The failure mode is cryptic and misleading: V8 prints Fatal javascript OOM in MemoryChunk allocation failed during deserialization and the process dumps core with SIGTRAP at startup. That looks like "the VM is too small" so the natural reaction is to scale memory, but the actual culprit is the kernel refusing W+X. Fix: set MemoryDenyWriteExecute=no on the unit (or pass --jitless to Node, accepting the perf hit). Same trap applies to .NET Core, PyPy, and any other JIT.
If a Node systemd service core-dumps at startup with a memory-shaped error, grep the unit for MemoryDenyWriteExecute before doing anything else — it's a 5-second check that rules out a 30-minute false trail.