E.2 — Paperless-ngx memory need, 20-document batch, PAPERLESS_TASK_WORKERS=1 x THREADS_PER_WORKER=1
Measured 2026-09-15 on scratch LXC 9202 (demo-hp). Guest 9201 not touched.
Setup: catalog templates/paperless-ngx/docker-compose.yml (app-catalog 882a43e) rendered as compose project
`plspike` (containers plspike-*), traefik labels/network dropped, webserver on 127.0.0.1:18765,
image ghcr.io/paperless-ngx/paperless-ngx:2.20.15, postgres:16-alpine (256M cap), redis:7-alpine (128M cap),
webserver cap raised to 2G so the peak is measured, not capped. Generated values filled by hand (redacted).
Input: 20 distinct 3-page PDFs (text-layer Helvetica, ~40 lines/page, distinct md5), posted concurrently
via POST /api/documents/post_document/ (token auth; token redacted, length 40).
Catalog today: paperless-webserver memory 768M (805306368 B), WORKERS=2, THREADS=1; postgres 256M; redis 128M
(each container has its own cap).

--- run output (verbatim) ---
cgroup: /sys/fs/cgroup/system.slice/docker-f4d92829277069229eb95b69a4696c509d779157bc96a799f571c8b13098795f.scope
limit memory.max: 2147483648
startup memory.peak (before upload): 624263168
memory.current before upload: 618651648
token length: 40
upload start 2026-09-15T07:38:32Z
200 doc05.pdf
200 doc08.pdf
200 doc02.pdf
200 doc03.pdf
200 doc12.pdf
200 doc09.pdf
200 doc07.pdf
200 doc18.pdf
200 doc04.pdf
200 doc01.pdf
200 doc06.pdf
200 doc15.pdf
200 doc20.pdf
200 doc11.pdf
200 doc13.pdf
200 doc14.pdf
200 doc19.pdf
200 doc17.pdf
200 doc10.pdf
200 doc16.pdf
07:38:38 tasks {'PENDING': 18, 'SUCCESS': 2}
07:38:48 tasks {'PENDING': 14, 'SUCCESS': 5, 'STARTED': 1}
07:38:58 tasks {'PENDING': 10, 'STARTED': 1, 'SUCCESS': 9}
07:39:08 tasks {'PENDING': 6, 'SUCCESS': 13, 'STARTED': 1}
07:39:19 tasks {'PENDING': 3, 'STARTED': 1, 'SUCCESS': 16}
07:39:29 tasks {'SUCCESS': 20}
upload end 2026-09-15T07:39:30Z
documents count: 20
final tasks: 20 {'SUCCESS': 20}
memory.peak after batch: 783294464
max sampled memory.current during batch (0.5s): 776806400
memory.events: low 0 high 0 max 0 oom 0 oom_kill 0 oom_group_kill 0 sock_throttled 0 
plspike-webserver oomkilled=false restarts=0 status=running memlimit=2147483648
plspike-postgres oomkilled=false restarts=0 status=running memlimit=268435456
plspike-redis oomkilled=false restarts=0 status=running memlimit=134217728

--- computation ---
memory.peak (whole container lifetime incl. startup + batch) = 783294464 B (747.0 MiB)
startup-only peak before upload                              = 624263168 B (595.3 MiB)
cap = peak x 1.5 = 1174941696 B (1120.5 MiB) -> rounded UP to a 256M multiple = 1280M (1342177280 B)

--- caveats ---
- The PDFs carry a text layer; Paperless may skip/lighten OCR for them. BIGNIGHT's OOM named `gs` (ghostscript)
  processes, so image-only scans may peak higher than this text-PDF batch. The 1.5x factor is the stated margin.
- With 1 worker the batch peak (783 MB) sits only ~2.7% under today's 768M cap (805 MB) — the single-worker
  change alone would leave almost no headroom; the cap raise is needed too.

--- teardown ---
docker compose down -v (project plspike: 3 containers, 3 volumes, network), rm -rf /tmp/plspike in 9202.
Images pulled only for the spike (paperless-ngx:2.20.15, postgres:16-alpine, redis:7-alpine) removed —
none were used by 9202's other containers (pre-spike image list had none of them).
