# P0 eager-RLS baseline: 1M rows per source mapping Date: 2026-08-12 Commit: `577ef2a` plus the uncommitted P0 benchmark/test checkpoint PostgreSQL: 17, local Apple Silicon development build Profile: `RUN_PROFILE=compact`, `SAMPLES=1`, `WARMUPS=0`, `graph.query_memory_mb=1024` ## Fixture - 1,000,000 scalar-key node rows - 1,000,000 composite-key node rows - 999,999 standalone relationship rows - 2,000,000 projected nodes and 1,999,998 directed edges - build time: 111,477 ms - reported projection memory: 176.25 MiB - source relation sizes: 107,003,904 bytes scalar nodes, 116,080,640 bytes composite nodes, and 82,771,968 bytes relationship rows ## Result The no-RLS depth-zero control completed in 3,712 ms. The development visibility metric reported 9 microseconds, zero hidden nodes, and zero hidden relationships; the remaining time includes query start and loading the persisted backend-local projection. The first node-RLS broad-allow depth-zero query did not finish after more than 600 seconds and was cancelled manually. PostgreSQL returned query-cancelled and the backend remained usable. This is a censored lower bound, not a completed latency sample. The eager builder scans every RLS-active registered source mapping before seed resolution. In this fixture one targeted depth-zero query therefore scans the million-row scalar and composite node mappings even though it requests one scalar identity. The observed result is sufficient to reject eager full-source visibility as the scalable targeted-query strategy. ## 10M decision A 10M-per-mapping graph profile was not executed on this workstation. The 1M RLS query already exceeded ten minutes and the 2M-node projection used 176 MiB before query workspace. Extrapolating this eager implementation to 10M would consume substantial local time and memory without changing the architectural decision. The benchmark runner retains a parameterized 10M soak profile for a dedicated benchmark host. P5 must produce completed 1M and 10M lazy/eager comparisons before the scalable strategy can ship. Exact SPI-call, key-scan, and byte-scan counts are recorded as unavailable in the runner until dedicated instrumentation exists; this checkpoint does not infer them from elapsed time. `observations.csv`, `database-metadata.csv`, and `run-metadata.txt` retain the values recorded during the manual run. The original per-statement log, exact unrounded timing sample, and source `EXPLAIN` plans were not retained, so this directory does not fabricate them after the fact. The hardened runner now retains those artifacts automatically, including on statement timeout.