Local Docker response-time chart showing direct upstream, ModSecurity NGINX, and Coraza Caddy median and p95 results plus memory snapshots.
The final run used 40 sequential localhost requests per path. The values are a reproducible micro-baseline, not a throughput or production capacity benchmark.

    Lab status

    Product
    Local response-time and resource baseline
    Status
    Completed hands-on test
    Updated
    2026-07-26

    Evidence policy

    WAFWiki separates verified smoke-test results from architecture diagrams and methodology notes. A smoke test proves one narrow local path; it does not claim full production readiness.

    Environment

    Reproducibility notes

    Host runtime

    Docker Desktop 29.2.0 on macOS, aarch64, 10 CPUs, 7.65 GiB assigned

    Sample shape

    40 sequential curl requests per path, 120 response-time samples total

    Direct control

    go-httpbin 2.21.0 on 127.0.0.1:18180

    ModSecurity path

    ModSecurity 3.0.16 + NGINX + OWASP CRS 4.25.0 on 127.0.0.1:18181

    Coraza path

    Coraza 3.7.0 + Caddy 2.11.2 + OWASP CRS 4.25.0 on 127.0.0.1:18182

    Measurement

    curl time_total, Docker stats --no-stream after request samples

    Commands

    How this lab can be reproduced

    Run the final sequential baseline

    scripts/run-waf-evidence-lab.sh

    The JSON summary contains 40 samples each for upstream, ModSecurity, and Coraza.

    Read the recorded values

    node --input-type=module -e 'const j=await import("./docs/lab-evidence/waf-engine-comparison-2026-07-26.json", { with: { type: "json" } }); console.log(j.default.benchmarks, j.default.resources)'

    The command prints median, p95, sample counts, and WAF container resource snapshots.

    Observed result

    What the hands-on test showed

    Direct upstream

    0.983 ms median

    The unprotected go-httpbin control recorded a 2.172 ms p95 in the final sequential run.

    ModSecurity path

    3.956 ms median

    The ModSecurity and NGINX path recorded a 5.518 ms p95 across 40 requests.

    Coraza path

    3.571 ms median

    The Coraza and Caddy path recorded a 4.904 ms p95 across 40 requests.

    Memory snapshot

    68.85 vs 57.2 MiB

    Docker reported 68.85 MiB for ModSecurity and 57.2 MiB for Coraza after the samples; no sizing conclusion is claimed.

    Performance winner

    Not established

    One sequential localhost run without concurrency, repetitions, isolation controls, or production traffic cannot rank capacity.

    direct upstream: median=0.983ms p95=2.172ms n=40
    ModSecurity + NGINX: median=3.956ms p95=5.518ms n=40
    Coraza + Caddy: median=3.571ms p95=4.904ms n=40
    ModSecurity memory snapshot: 68.85MiB
    Coraza memory snapshot: 57.2MiB
    measurement mode: sequential localhost curl time_total

    Evidence context

    The latency baseline includes an unprotected upstream control.

    Adding the direct route makes the measurements easier to interpret, but the run still cannot isolate every proxy, engine, container, scheduler, logging, and warm-up effect.

    Shared Docker topology for the direct upstream, ModSecurity NGINX, and Coraza Caddy response-time paths.

    Open evidence

    Download the sanitized result files.

    The files expose the status matrix and versioned summary without publishing raw container logs or unrelated local data.

    Download evidence summary JSON

    Pinned image IDs, component versions, host details, request results, latency samples, resource snapshots, and limitations.

    Limitations

    What this result does not prove

    Related research

    Continue researching Local response-time and resource baseline