Log Analytics ingestion cost
07 Oct 2026
Log Analytics: the ingestion bill nobody forecast
Nobody approves a Log Analytics bill. Someone opens a resource, clicks
Diagnostic settings, ticks allLogs because it's
the safe-looking box, and points it at the workspace. A setting that adds
20 GB a day is 7,300 GB a year of billable ingestion. Multiply that by your
region's per-GB price and "five-figure decision" stops sounding like an
exaggeration. Nothing in that dialog shows a price.
This is the playbook for taking that decision back: find out what you're paying to ingest, then decide category by category what's worth collecting, which plan it lands in and how long it stays. Six steps, each with a check that tells you it's done.
Step 1: find out which tables you're paying for
The workspace records its own consumption in
the Usage table, and that table is
free
to ingest, like AzureActivity, Heartbeat and
Operation. Microsoft's
usage
analysis queries start here. Run this one and sort by the total:
Usage
| where TimeGenerated > ago(32d)
| where StartTime >= startofday(ago(31d)) and EndTime < startofday(now())
| where IsBillable == true
| summarize BillableDataGB = sum(Quantity) / 1000. by DataType
| sort by BillableDataGB desc
In most workspaces, three or four tables carry most of the bill.
AzureDiagnostics, Perf, ContainerLog
and the App* tables are the usual suspects. To see which resource
is sending the data, the same page has a find query grouped by
_ResourceId. Run it over a single day, because it scans every
table. Done when each of the top five tables has a named
owner who can say why it's collected.
Step 2: replace allLogs with a list you've read
allLogs means every category the
resource has today, and more: the docs say that
if
the categories in the group are updated, your log collection is modified
automatically. When Microsoft adds a verbose category to a service,
your ingestion goes up and nobody had to change a thing. A diagnostic
setting also can't filter within a category. Each category is
either collected in full or not collected at all.
Go through the settings that feed your top tables and tick the categories
someone actually queries. The audit group is often the right
smaller default. Untick AllMetrics unless you need to join
metrics with logs in KQL: platform metrics are
collected
automatically and already available in metrics explorer, so sending them
to the workspace means paying to ingest a copy. Done when no
setting on a high-volume resource uses allLogs without a written
reason.
Step 3: give every category a destination before you collect it
Ingestion price depends on the table plan, and the plan is set per table. Analytics is billed per GB with 31 days of retention included, and queries are free. Basic costs less to ingest, but every query is billed per GB scanned. Auxiliary is the cheapest to ingest and the most limited. So the question for each category isn't only "do we need it?" It's "how will it be read?"
Two details decide whether this works. First, Basic and Auxiliary
aren't
available for every Azure table, and a table's plan can change only once a
week. Moving a table to Auxiliary also
stops any alerts that run on it. Second, a table can only have one plan, so
resource logs need a table of their own. In Azure diagnostics mode every
service writes into the shared AzureDiagnostics table. Microsoft
says to
use
resource-specific mode for any new diagnostic setting, which gives each
category its own table. When you switch an existing setting, the old rows stay
in AzureDiagnostics until retention removes them.
Done when every high-volume table is on the plan that matches
how it's read.
Step 4: drop rows and columns at ingestion
Diagnostic settings don't use a data
collection rule, so their transformations go in the
workspace
transformation DCR. You get one per workspace, and it can cover any
supported table. A KQL where drops the informational rows and
a project-away drops the columns nobody queries.
There's a catch. On Analytics and Basic tables, if a transformation
drops
more than 50% of the incoming data, the part above 50% is billed as data
processing: 20 GB in, 12 GB dropped, 2 GB billed. (Workspaces with Sentinel
enabled are exempt.) If you find yourself dropping most of a category, you
shouldn't be collecting that category at all. That's step 2.
And check your schemas too: column values that
don't
match the destination table are billed even though they're never stored.
Done when the top table's daily volume in Usage
drops, and the alerts that read it still fire.
Step 5: set retention per table, and know what doesn't save money
Analytics retention can go up to two years, and total retention up to 12. Anything past the analytics period moves to low-cost long-term retention, where you read it with a search job. That's where compliance data belongs. Three things that look like savings and aren't:
- Going below 31 days. You can set analytics retention as low as four days, but 31 days are already in the ingestion price, so it doesn't reduce costs.
- Purge. Deleting data with the Purge feature doesn't affect retention costs. Only a shorter retention period does.
- Expecting it to apply today. When you shorten total retention, Azure Monitor waits 30 days before it removes the data, so you can undo a mistake.
Done when every table that keeps data longer than the workspace default has a reason written next to it.
Step 6: add a tripwire, then commit
The early warning is a log alert on Usage. Microsoft's
example
fires when billable ingestion goes over 50 GB in 24 hours. Set yours at about
1.5 times your new baseline. Only then look at
commitment
tiers: they start at 100 GB a day, save up to 30%, lock you in for 31 days,
and cover Analytics ingestion only. Committing before steps 1–5 locks in the
volume you were about to cut.
_LogOperation | where Detail contains "OverQuota" so the
outage gets noticed.
Done when the alert exists, the cap is set, and the tier matches the baseline after cleanup.
- Azure Monitor Logs cost calculations and options — free tables, billing for columns that don't match the schema, table plans and 31 days included, commitment tiers (100 GB/day, up to 30%, 31 days, Analytics only), Purge doesn't lower retention cost.
- Analyze usage in a Log Analytics workspace — the Usage queries, per-resource find queries, and the 50 GB/24h ingestion alert.
- Diagnostic settings in Azure Monitor — allLogs picks up new categories automatically, no filtering within a category, platform metrics already in metrics explorer.
- Transformations in Azure Monitor — the workspace transformation DCR, and the data processing charge above 50% filtered.
- Configure a table plan — plan support varies by table, alerts stop on Auxiliary, one switch per table per week.
- Manage data retention in a Log Analytics workspace — 2-year analytics and 12-year total retention, no saving below 31 days, the 30-day wait after shortening.
- Set daily cap on Log Analytics workspace — overshoot is still billed, collection stops, fixed reset hour, Auxiliary not capped, the OverQuota alert.
The Usage table shows what's inside one workspace. It won't
tell you which workspace, in which subscription, is the one that grew.
GraphPaaS reads Azure spend for each tenant
and breaks it down by resource, resource type and resource group, with a
month-by-month
drill-down. A workspace that jumped after someone ticked
allLogs shows up as its own line, and if the
tags
reach the cost data, so does the team that owns it. For an MSP, that works
across every client tenant from the same screen.
See which workspace grew, in every tenant you manage, before the invoice tells you.
Break down your Azure bill →