Skip to content

Azure per-resource cost (Cost Management Export)

By default, CloudOptify reads Azure cost from the Cost Management query API — accurate, but rate-limited, limited to a short backfill on first sync, and grouped without resource-level tags. To get exact, per-resource cost with deep history and tags, connect an Azure Cost Management export delivered to a storage account you own.

This is optional. Leave the export unconfigured and CloudOptify keeps using the Cost Management API exactly as it does today. Once an export is connected, CloudOptify ingests it automatically and the query API is only used as a small freshness top-up for the last day or two.

The export becomes your cost backbone instead of a live API call, which unlocks a step change in both reliability and depth:

  • Billing-accurate numbers. Costs come straight from the same export Azure uses to generate your invoice — no estimation, no rounding drift.
  • No rate limits. Refreshes read your own storage instead of calling the throttled Cost Management query API, so large estates stop hitting 429 errors during scheduled syncs.
  • Deeper history, immediately. An export backfills up to 13 months the moment it lands. Without one, the first sync pulls a 3-month window and history builds forward from there (see How much history you get below).
  • Real per-resource drill-down. Cost Explorer shows exact, billed cost per resource rather than an inventory-weighted estimate.
  • Tag-based cost allocation. Cloud Groups can allocate spend by resource tag — the “business mapping” model — pulling in tagged resources across accounts, not just the ones explicitly assigned to a group.
  • Cost by Region. See exactly where in the world your spend lives, split by provider — for data-residency checks and catching unexpected egress.
  • Top Resources. An org-wide, cross-cloud ranking of your most expensive individual resources — the fastest way to find rightsizing and cleanup targets.

This is the single biggest practical difference between the two cost sources, so it is worth being precise about.

Without an export — 3 months, then it grows

Section titled “Without an export — 3 months, then it grows”

The Cost Management query API is rate-limited per subscription, and the limit is weighted by how much a query asks for. Requesting a full year of daily cost in one go is the most expensive shape there is, and on smaller subscriptions (MSDN, dev/test, sandbox) it frequently fails with 429 Too many requests — leaving you with no history rather than a little.

CloudOptify therefore asks for a 3-month window on the first sync, split into month-sized requests so a rate limit costs you one month rather than the whole year.

History then accumulates. Every later sync re-reads only the recent, still-changing months (the current month plus the previous two, since clouds keep restating recent bills for credits and late usage). Nothing already collected is deleted.

So the picture over time looks like this:

Time since connecting History you hold
Day 1 ~3 months
3 months later ~6 months
6 months later ~9 months
12 months later ~15 months

The one thing that never happens on its own is going backwards: periods older than your first sync stay out of reach through the query API. If you need them, connect an export.

With an export — up to 13 months on day one

Section titled “With an export — up to 13 months on day one”

An export reads from your own storage account, so it isn’t subject to the query API’s rate limits at all. On its first ingest CloudOptify pulls the full archive Azure retains — up to 13 billing periods — and every sync after that refreshes the current and previous period.

If deep history matters to you (year-over-year comparisons, budget baselines, showback for a full fiscal year), connect an export rather than waiting for the query API to accumulate.

An Azure export’s scope is fixed when it’s created, and it determines which subscriptions end up in the file. This is the single most common source of confusion, because an export that covers one subscription looks identical to one that covers fifty — same storage account, same format, same schedule.

CloudOptify reads whatever the export contains, so the question is simply: how many exports do you need to cover everything you’ve selected?

Scope Covers Requires Exports needed
Subscription That one subscription Any Azure agreement One per subscription
Resource group One resource group Any Azure agreement Not recommended — misses everything outside it
Management group Every subscription beneath it EA or MCA One, for the whole group
Billing account / profile Everything on the agreement EA or MCA One, for everything

If you’re on Enterprise Agreement (EA) or Microsoft Customer Agreement (MCA)

Section titled “If you’re on Enterprise Agreement (EA) or Microsoft Customer Agreement (MCA)”

Export once at management group or billing account scope. One export covers every subscription beneath it, including subscriptions added later — which means no maintenance as your estate grows. This is the recommended setup for any organization with more than a handful of subscriptions.

If you’re on pay-as-you-go, Visual Studio / MSDN, or another WebDirect offer

Section titled “If you’re on pay-as-you-go, Visual Studio / MSDN, or another WebDirect offer”

These subscriptions are billed individually and have no parent billing scope to export from. You’ll need one export per subscription. Attempting a management-group export returns:

No EA Subscriptions for Management Group with managementGroupId: <id> were found

That error is not a permissions problem and can’t be fixed by granting roles — the subscriptions simply aren’t part of an enrollment that supports rolled-up exports.

Multiple exports can deliver to the same storage account, container, and directory. Azure gives each export its own subfolder, and CloudOptify ingests them together as a single dataset — so covering five subscriptions means five exports but still only one storage account to create, secure, and pay for.

Once an export has delivered, open Connections in CloudOptify. If some selected subscriptions aren’t covered, the connection card says so directly:

Billing export covers 1 of 3 subscriptions

and lists the ones still using the Cost Management API. Those subscriptions keep syncing normally — just through the rate-limited API, with a shorter history — so this is a gap to close rather than a failure.

Section titled “Option 1: Let CloudOptify create the export for you (recommended)”

CloudOptify can create the scheduled export and backfill the last 12 months automatically, using the same service principal you already granted read access to. This is the fastest path — no manual export configuration in the Azure portal.

  1. In the portal, go to Cloud Connections → your Azure tenant → Set up billing export.
  2. Enter the storage account name and container you want the export delivered to (create an empty storage account/container first if you don’t have one — Azure docs: create a storage account).
  3. Click Verify & save — CloudOptify checks the service principal can read the container before saving anything.
  4. Click Create exports automatically. CloudOptify creates a daily FOCUS export for every active subscription under the tenant, plus one-time historical runs covering the last 12 months.

This step needs the service principal to additionally hold Cost Management Contributor on each subscription (to create the export) and Reader on the storage account’s subscription (to resolve it). Grant these the same way you granted the original read-only role — see Connect Azure.

Skip to Timing once this finishes — steps A and B below are only needed for the manual path.

If you’d rather configure the export yourself, or your organization requires exports to be provisioned through its own change process:

  1. Azure Portal → Cost Management + Billing → Cost Management.
  2. Change the scope selector at the top to the subscription, management group, or billing account you decided on in Choosing the export scope. This is the step that determines what the export contains, and it’s easy to miss — the default scope is whichever one you last viewed.
  3. Exports → + Create.
  4. Export name: e.g. cloudoptify-cost-export.
  5. Export type: FOCUS cost (recommended) — or Cost and usage details (actual/amortized) if your organization already standardizes on it. CloudOptify recognizes both formats. Use the same type for every export delivering to one container. If you use cost and usage details, choose actual cost: the amortized version spreads reservation purchases over time, so Billed Periods can’t match it to the invoice.
  6. File format: CSV or Parquet — either is supported, compressed or not.
  7. Frequency: Daily export of month-to-date costs.
  8. Storage account: select or create the storage account and container to deliver to; note the directory path if you set one.
  9. Create.

Repeat for each subscription if you’re on a WebDirect agreement.

For history, also run a one-time export covering the months you want backfilled — Azure exports don’t backfill automatically the way AWS Data Exports do, so without this step only data from the day you create the export onward will appear.

Note these values for CloudOptify:

Field Example
Storage account mycloudoptifyexports
Container cost-exports
Directory path (optional) exports
Export name (recommended) cloudoptify-cost-export

B. Grant the connection’s service principal access to the storage account

Section titled “B. Grant the connection’s service principal access to the storage account”

In the Azure Portal, go to the storage account → Access Control (IAM) → Add role assignment → Storage Blob Data Reader → assign it to the same app registration / service principal CloudOptify already uses for this tenant.

In the portal → Cloud Connections → your Azure tenant → Set up billing export → enter the storage account, container, directory path, and export name → Verify & save. CloudOptify tests storage access before saving (it lists the container with the service principal), so a wrong name or missing role fails immediately with a clear message.

Setting the export name is optional but recommended: it scopes ingestion to that one export, so a container holding more than one export (for example both actual and amortized) can’t be double-counted.

If you used Option 1, the historical backfill runs are queued immediately and typically land within a few hours; the daily export starts delivering from the next day. If you used Option 2 without a historical export, only data from the day the export was created forward will appear — go back and add a one-time export for the months you want backfilled.

Until the first file lands, CloudOptify keeps using the Cost Management API, and the export ingestion simply reports “no export data files found yet” — it picks up automatically once data arrives. After that, each refresh re-checks the current and previous month (the export restates the running month on every drop, which CloudOptify handles), plus a small query-API top-up for the last day or two to keep “today’s spend” current.