This bundle is designed for occasional, authorized debugging in production-like environments. It is not a zero-cost no-op, but under normal conditions the overhead is small and predictable. There is no background worker, no database, and no I/O beyond the HTTP response you already send.
| Scenario | Server impact |
|---|---|
Gate closed (enabled: false, wrong role, missing query param) |
Negligible — one gate check per cdbg() call, then an immediate return |
Gate open, no cdbg() / {% cdbg %} calls |
Negligible — empty registry; response subscriber exits early |
| Gate open, a few debug calls on an HTML page | Low — backtrace + JSON normalization + small script injection |
| Gate open, many calls or huge payloads | Noticeable — CPU for normalization, memory for registry, larger HTML body |
For most applications, leaving a handful of cdbg() calls in code used only by trusted staff is acceptable. Spraying debug calls inside tight loops or dumping entire Twig contexts on every request is not.
On every main HTTP response, ConsoleDebugResponseSubscriber runs at priority -4096 (after the Web Profiler). Cost when the registry is empty:
- A few condition checks (
isMainRequest,registry->isEmpty())
No body read, no JSON encoding, no HTML mutation.
When the gate returns false:
ConsoleDebugGateInterface::isEnabled()(default: master switch + Symfony authorization checks)- Return — no backtrace, no normalization, no registry write
Typical cost: microseconds per call, dominated by the security authorization checker when roles are evaluated.
When collection is allowed:
- Gate check (same as above)
debug_backtrace()— limited to 6 frames for PHP calls; Twig tag uses template name/line insteadDebugValueNormalizer— walks arrays/objects up to depth 8; objects without__toStringbecome{ object, hash }stubs (no full property dump like VarDumper)- Registry append — in-memory list for the current request
Cost scales with number of calls and size/complexity of values.
Only when all of the following are true:
- Registry has entries
- Response is HTML (
text/htmlorapplication/xhtml+xml) - Body is non-empty
- Script marker not already present
Then the subscriber:
- Reads the full response body (
getContent()) json_encodes all collected entries (with hex-escaping for safe embedding)- Inserts a
<script type="application/json">payload and a runner<script>before</body>(or appends if no</body>) - Writes the modified body back
Effects:
- Extra CPU proportional to response size + payload size
- Larger HTML download (payload duplicated in a JSON script block)
- Slightly higher memory peak (body string + JSON)
Non-HTML responses (JSON API, files, streams) skip injection, but any cdbg() calls during that request still paid collection cost and held data in memory until the request ends.
| Tool | Blocking? | Typical server cost |
|---|---|---|
dd() / dump() + die |
Yes — stops the request | High impact by design |
Web Profiler / dump() in HTML |
No | Renders VarDumper HTML into the page (often heavier visually and in payload) |
cdbg() |
No | Serializes to JSON once; console rendering is client-side |
| Monolog / structured logging | No | Different channel; better for audit trails, not interactive inspection |
cdbg() is lighter than halting the request and usually lighter than embedding VarDumper output in HTML, but heavier than doing nothing.
- Treat
cdbg()like temporary instrumentation — remove or reduce before merging hot paths, or keep calls in branches that only run for debug users. - Use roles + optional
query_paramin production so collection stays limited to trusted sessions. - Set
enabled: falsein environments where debug must be impossible (when@prodin config), even if stray calls remain in code. - Avoid large dumps — prefer scalars, small arrays, IDs.
{# full context #}{% cdbg %}can serialize every Twig variable. - Avoid high-frequency calls — not inside
foreachover thousands of rows; log a summary instead. - API / JSON controllers — if you leave
cdbg()in an API action, data is still collected server-side even though nothing is injected; prefer HTML debug pages or logging for APIs.
# config/packages/nowo_console_debug.yaml
when@prod:
nowo_console_debug:
enabled: false # hard off in production
when@dev:
nowo_console_debug:
enabled: true
roles: [ROLE_CONSOLE_DEBUG]
# query_param: console_debug # optional extra guard in staging/prodSee Configuration for all options.
- No reseñable penalty for anonymous users or when the bundle is disabled: one cheap gate check per call.
- Low penalty for authorized HTML debugging with a few small
cdbg()calls — the intended use case. - Measurable penalty only when you collect large payloads, call debug very often, or inject into large HTML responses.
Monitor response times and HTML size if you debug heavily in staging; adjust roles, enabled, and what you dump accordingly.