Log cost
Log bills scale with what you send, and a logger that writes a line per step sends the same request context over and over. Every line carries its own level, timestamp, host, and request bindings. Four lines, four copies.
evlog emits one event per request instead, so that context is written once. This page measures the difference and lets you price it against your own traffic.
Try it against your numbers
Requests / month
Log lines per request, today 4
Sampling, kept on both sides 100%
4 lines / request
- Events
40M40M - Data
7.4 GB7.4 GB
evlog, 1 event
- Events
10M10M - Data
3.2 GB3.2 GB
Byte counts measured by serializing the checkout request above through pino 10 and evlog: 4 lines totalling 736 B against 1 event of 322 B, so 184 B per line and 322 B per event. Your fields differ, so treat the shape as the method, not the answer.
List rates read on 14 August 2026 (Datadog: ingest + indexing, 15-day retention). Vendors change pricing without notice, which is why every rate here is editable. Free tiers, committed-use discounts and retention add-ons are not modelled. Sampling is applied to both columns, because any logger can drop events: it lowers each bill and leaves the ratio between them alone.
Where the byte counts come from
Both shapes are the checkout request documented on Performance, serialized through the real libraries rather than estimated.
const log = createLogger({ method: 'POST', path: '/api/checkout', requestId: 'req_abc' })
log.set({ user: { id: 'usr_123', plan: 'pro' } })
log.set({ cart: { items: 3, total: 9999 } })
log.set({ payment: { method: 'card', last4: '4242' } })
log.emit({ status: 200 })
const child = pinoLogger.child({ method: 'POST', path: '/api/checkout', requestId: 'req_abc' })
child.info({ user: { id: 'usr_123', plan: 'pro' } }, 'user context')
child.info({ cart: { items: 3, total: 9999 } }, 'cart context')
child.info({ payment: { method: 'card', last4: '4242' } }, 'payment context')
child.info({ status: 200 }, 'request complete')
| Events | Bytes | |
|---|---|---|
| pino, 4 lines | 4 | 736 |
| evlog, 1 event | 1 | 322 |
| Difference | 75% fewer | 56% fewer |
The two numbers differ because consolidation removes duplicated envelope, not payload. level, time, pid, hostname, method, path, and requestId are written four times by pino and once by evlog, and the four msg strings disappear entirely. The fields you actually set are written once either way.
user object on every line saves more. The method transfers, the number does not.Which number moves your bill
Providers meter logs in one of two ways, and that decides which saving you actually collect.
| Metered by | Saving you collect | Providers |
|---|---|---|
| Gigabytes ingested | The 56% byte figure | Grafana Cloud, Sentry, PostHog, Better Stack, Axiom |
| Gigabytes and indexed events | The 75% event figure, on the line item that usually dominates | Datadog |
Per-gigabyte billing is the common case, so most teams collect the byte saving. Datadog is the outlier worth checking: it bills ingestion per gigabyte and indexing per million events, and at production volumes the indexing line is the larger of the two, so the event count is what moves.
Rates were read on 14 August 2026 and are list prices, before free tiers, committed-use discounts, and retention add-ons. They are inputs in the calculator above for exactly that reason.
Sampling moves both columns
The calculator applies sampling to both shapes, which is the only fair way to model it. Dropping events is not something evlog does and other loggers cannot: you can filter by level in any logger, or sample in the transport. Applying it to one side only would flatter evlog with a saving that is not evlog's. Pull the slider down and both bills fall together while the gap between them holds.
It is still the larger lever. Consolidation is bounded, because you cannot send fewer than one event per request. Sampling is not: head sampling drops events by level at emit time, and tail sampling force-keeps the ones you would have wanted, so errors and slow requests survive a rule that discards the rest. Volume stops tracking traffic and starts tracking signal, which is the only version of this that keeps working as you grow.
What evlog changes is the unit sampling operates on. Dropping a line loses part of a request; dropping an event loses a whole one, and keeping an event keeps all of it.
Ask it from your editor
The same calculation is an MCP tool on this site's server, so an assistant connected to https://evlog.dev/mcp can answer it directly:
estimate-log-cost({ requestsPerMonth: 10000000, linesPerRequest: 4, provider: "datadog" })
It returns both shapes, the saving, and the basis it used: the measured byte counts, which rates it applied, and the date those rates were read. Pass perGb and perMillionIndexed to price a provider that is not in the list, or to correct one whose pricing has moved.
Next
- Sampling — the two tiers, and what each one costs you in visibility
- Performance — the benchmarks these byte counts come from
- Drain adapters — every destination, and how to change your mind later