Structured logging and cost: does JSON make your bill bigger or smaller?
JSON logs are more verbose per line than plain text, which raises ingestion bytes. They are also queryable without full-text scans, which lowers query cost and enables filtering. The net effect depends on how you use them.
Quick answer
JSON logging typically increases raw bytes per line by 40% to 120% because every value carries a key name and punctuation, so a 180-byte text line becomes 300 to 400 bytes. At CloudWatch's $0.50 per GB, converting 100 GB/day of text logs to JSON adds roughly $750 per month in ingestion. But structured logs cut query cost sharply (Logs Insights scans less to answer a field query), enable precise agent-side filtering that unstructured logs cannot support, and make sampling and field trimming possible. Structured logging pays for itself only if you actually trim fields and filter at the agent.
Structured logging is treated as unambiguously good practice, and operationally it is. Financially it is a trade. JSON is a verbose encoding, and you pay per byte ingested. The honest position is that structured logs cost more to ingest and less to use, and whether that nets out in your favor depends entirely on whether you exploit the structure or just emit it.
The byte overhead, measured
| Format | Example line | Bytes |
|---|---|---|
| Plain text | 2026-09-21 10:14:02 INFO GET /orders 200 42ms user=8812 | 58 |
| JSON, compact keys | ts, lvl, m, p, s, d, u | ~102 |
| JSON, descriptive keys | timestamp, level, http_method, http_path, status_code, duration_ms, user_id | ~168 |
| JSON with full context | plus service, version, region, pod, trace_id, span_id, env | ~380 |
The pattern is clear: key names and JSON punctuation roughly double the line, and the context block that good structured logging encourages you to attach can double it again. A realistic production JSON line with service identity and trace correlation runs 300 to 500 bytes against 150 to 200 for the text equivalent.
At scale that is money. A service emitting 500 million log lines per month at 180 bytes ingests 90 GB, costing $45 on CloudWatch. The same lines at 380 bytes ingest 190 GB, costing $95. Multiply across 40 services and the JSON overhead alone is $2,000 per month. On Azure Monitor analytics logs at roughly $2.76 per GB, the same overhead is $11,040 per month.
What structure buys back
Query cost is the first return. CloudWatch Logs Insights charges $0.005 per GB scanned, and while the scan is over raw bytes either way, structured logs let you write selective queries that a parsing step would otherwise need. More importantly, structured logs let you use metric filters to extract numbers without running queries at all, converting a recurring per-GB scan into a metric that costs $0.30 per month.
Agent-side filtering is the second and larger return. You cannot reliably drop unstructured log lines by field value, because there are no fields. With JSON, a Fluent Bit or Vector filter can drop every line where path matches a health endpoint, sample every line where status is 200 and duration is under 100ms, and keep every line where level is ERROR. Those filters are exactly the volume reduction tactics that cut 50% to 70% of ingestion, and structure is the prerequisite for applying them precisely.
Field trimming is the third. Once fields are named, you can drop the ones nobody queries. Auditing which fields appear in actual queries over 90 days and removing the rest routinely cuts 20% to 40% of the structured line size, which more than recovers the JSON overhead. Unstructured logs offer no equivalent lever because you cannot remove what you cannot address.
The net, worked
| Scenario | GB/day | CloudWatch $/month |
|---|---|---|
| Text logs, no filtering | 100 | $1,500 |
| JSON logs, no filtering | 200 | $3,000 |
| JSON, probes dropped | 150 | $2,250 |
| JSON, probes dropped + 5% success sampling | 48 | $720 |
| JSON, plus unused fields trimmed | 33 | $495 |
Adopting JSON without changing anything else doubles the bill. Adopting JSON and then using it cuts the bill by two thirds against the text baseline. The decision is not "structured or not", it is "structured and exploited, or structured and merely emitted". The middle row is the trap most teams sit in.
Practical byte discipline
Use short but readable key names. The difference between http_response_status_code and status is 26 bytes per line, which at 500 million lines per month is 13 GB, or $6.50 on CloudWatch and $36 on Azure. Across a schema with 20 fields the savings compound.
Do not repeat what the platform already records. Service name, environment, region, and cluster are usually available from the log group name, log stream name, or resource labels. Emitting them in every line is pure duplication. Similarly, do not emit both a human-readable message and the structured fields that message restates; pick one.
Omit null and empty fields rather than emitting them. A schema with 25 optional fields where 18 are typically null wastes roughly 180 bytes per line on nothing. Most logging libraries have an option for this and most teams leave it off.
Where structure earns its cost outright
Two cases make structured logging worth the bytes regardless of arithmetic. The first is tiered ingestion: you cannot route intelligently between expensive and cheap tiers without fields to route on, and moving 70% of volume from $0.50 per GB to $0.25 per GB halves the meter that dominates the bill. The second is correlation: a trace_id field that links logs to traces turns two separate debugging tools into one workflow, and the incident time saved is worth more than the ingestion delta.
Log groups, agent configuration, and routing rules all live in Terraform, so price the logging estate from the plan against the resource catalog and make the cost of a schema change visible before it ships to forty services.
FAQ
Does JSON logging cost more than plain text?
Yes, in raw ingestion. Key names and punctuation typically increase line size by 40% to 120%, so a 180-byte text line becomes 300 to 400 bytes in realistic production JSON with service identity and trace correlation. At CloudWatch's $0.50 per GB, doubling 100 GB/day of logs adds roughly $750 per month. On Azure Monitor analytics logs at about $2.76 per GB, the same overhead adds around $4,140 per month.
How does structured logging reduce cost?
Through three levers. Agent-side filtering can drop or sample lines precisely by field value, which unstructured logs cannot support reliably. Field trimming lets you remove fields nobody queries, often 20% to 40% of line size. And metric filters can extract numbers into $0.30 per month metrics instead of recurring $0.005 per GB query scans. Together these typically cut two thirds of ingestion against a text baseline.
What is the net cost effect of adopting structured logging?
It depends entirely on whether you exploit the structure. Adopting JSON with no other change roughly doubles ingestion: 100 GB/day becomes 200 GB/day, $1,500 becomes $3,000 on CloudWatch. Adopting JSON and then dropping probe lines, sampling successes at 5%, and trimming unused fields brings it to roughly 33 GB/day and $495 per month, a third of the original text-based bill.
How should I design a log schema to minimize bytes?
Use short but readable key names, since status versus http_response_status_code saves 26 bytes per line, or 13 GB per month at 500 million lines. Do not repeat data already available from the log group name, stream name, or resource labels, such as service, environment, and region. Do not emit both a prose message and structured fields restating it. And configure the library to omit null and empty fields.
When is structured logging worth the extra bytes regardless?
When you use tiered ingestion or trace correlation. Routing between a $0.50 per GB tier and a $0.25 per GB tier requires fields to route on, and moving 70% of volume to the cheap tier halves the dominant meter. And a trace_id field linking logs to traces merges two debugging workflows into one, where the incident time saved routinely outweighs the ingestion difference.
How does C3X help with logging schema cost?
Log groups, their ingestion class, retention, agent configuration delivered via launch templates or config maps, and routing rules are Terraform resources. C3X prices that estate from the plan, so the infrastructure implications of a schema or tiering change carry a number in the pull request rather than arriving as an ingestion increase spread across forty services on next month's bill.
What to do next
Make logging schema decisions with a price attached. C3X reads your Terraform and prices log groups and tiers against a live catalog. Start with the quickstart.
Share this post
Try C3X on your own Terraform
Free and open source. No API key required. One command to install, one command to estimate.