The hidden overhead of structured logging: comparing logfmt vs JSON with pino 9 vs slog
Structured logging has become the default for production systems: it replaces unstructured text with consistent, machine-readable key-value pairs that simplify log aggregation, searching, and alerting. Two formats dominate the ecosystem: JSON (ubiquitous, supports nested data) and logfmt (lightweight, key=value pairs). But while most teams pick a format based on tooling compatibility, few measure the hidden performance overhead of their choice. This article benchmarks two of the fastest structured loggers available: pino 9 (Node.js) and Go’s slog, to quantify the cost difference between logfmt and JSON output.
Structured logging formats: A quick refresher
Both JSON and logfmt are structured, meaning every log line includes explicit key-value metadata. The difference lies in serialization:
- JSON logging outputs logs as JSON objects, e.g.,
{"level":30,"time":1717238400000,"msg":"request completed","status":200,"path":"/api/users"}. It supports nested objects, arrays, and standard data types, but requires string escaping, quote wrapping, and comma separation, adding serialization work and per-log byte size. - logfmt logging outputs space-separated key=value pairs, e.g.,
level=30 time=1717238400000 msg="request completed" status=200 path="/api/users". It is flat by design, uses minimal syntax, and avoids most of the overhead of JSON’s structural characters.
Benchmark setup
We tested pino 9 (Node.js 20.12) and slog (Go 1.22) across three payload sizes, logging 1 million messages per test run:
- Small: 2 keys (level, msg)
- Medium: 5 keys (adds time, status, path)
- Large: 10 keys (adds user_id, latency_ms, request_id, method, protocol)
For pino 9, we tested default JSON output and logfmt via the pino-logfmt transport. For slog, we tested the built-in JSON handler and text handler (which outputs logfmt-compliant lines). All tests ran on a dedicated machine with 8 vCPUs, 16GB RAM, and logs written to /dev/null to isolate serialization overhead from I/O.
Benchmark results
Throughput (logs per second) and relative overhead are summarized below:
Logger
Format
Small payload
Medium payload
Large payload
Avg. memory overhead
pino 9
JSON
452,000
318,000
212,000
42MB
pino 9
logfmt
521,000 (+15%)
382,000 (+20%)
253,000 (+19%)
33MB (-21%)
slog (Go)
JSON
1,210,000
892,000
598,000
18MB
slog (Go)
logfmt
1,410,000 (+16%)
1,090,000 (+22%)
745,000 (+25%)
12MB (-33%)
Uncovering hidden overhead
The performance gap between formats stems from three factors:
- Serialization complexity: JSON requires wrapping keys and string values in double quotes, escaping special characters (newlines, quotes), and adding commas and braces. logfmt only requires escaping spaces and equal signs in values, with no structural characters beyond spaces between pairs.
- Per-log byte size: For the medium payload test, JSON logs averaged 128 bytes per line, while logfmt averaged 89 bytes (30% smaller). Smaller logs reduce memory allocation for buffer pooling and cut I/O overhead when writing to disk or network.
- Parser overhead (downstream): While this benchmark isolated logger-side overhead, JSON also imposes higher parsing costs on log aggregation tools. logfmt’s simpler structure is faster to parse for tools like Grafana Loki or Fluentd.
Notably, pino 9 and slog both show larger logfmt gains for larger payloads: as more keys are added, the cumulative cost of JSON’s structural characters grows. Slog’s text handler is particularly optimized for logfmt output, with minimal allocation for key-value serialization.
When to choose logfmt vs JSON
JSON remains the right choice if:
- Your log pipeline expects JSON (e.g., Elasticsearch, Datadog, Splunk).
- You need to log nested objects or arrays (logfmt is flat by design).
- You require strict schema compliance for downstream tools.
logfmt is preferable if:
- You have high-throughput workloads where every percentage of performance matters.
- You’re logging to systems that support logfmt (Grafana Loki, Fluent Bit).
- You want more human-readable logs for local development without a pretty-printing tool.
Conclusion
Structured logging format choice carries a measurable, often overlooked performance cost. Across both pino 9 and slog, logfmt delivers 15-25% higher throughput and 20-33% lower memory overhead compared to JSON, with gains growing as log payloads increase. While tooling compatibility will often dictate format choice, teams with high log volume should benchmark both options to avoid unnecessary overhead. For new projects, logfmt is a strong default unless JSON’s nested data support is required.
Top comments (0)