Account Management already gives you a built-in forecast, but it only goes as far as environment and capability level. When you need to understand growth rates, project spend across 30/60/90-day windows, or calculate exactly when a budget alert will fire, DQL fills the gap.
This tutorial uses Full-Stack Monitoring as a worked example throughout. Once you understand the pattern, applying it to any other capability is a matter of changing the filter event.type and the rate card values.
All USD figures in this tutorial use the public list price of $1,000 per 100,000 GiB-hours (March 2026). Actual costs depend on your negotiated DPS contract. Use these queries for directional analysis and relative comparisons, not invoice reconciliation.
This tutorial is for FinOps practitioners, engineers, and platform team leads who need to go beyond the Account Management overview, either to quantify a trend they can already see, or to set an evidence-based budget alert threshold.
In this tutorial, you'll learn how to:
dt.system.events table in at least one environment.dt.system.events, start with Where to view your costs.Before writing any DQL, check what Account Management already shows you.
Go to Subscription > Overview and review the Budget Summary:
| Component | What it tells you |
|---|---|
Annual commitment + days remaining | Your contractual baseline. |
Forecast line chart | Dynatrace's own ML projection through end of subscription period. |
Forecast events panel | The date your forecasted usage will exceed your annual commitment, plus the projected on-demand overage. |
The built-in forecast becomes available once your account has 15 or more days of cost data. Until then, use the DQL steps below.
Review your budgets (Subscription > Cost Management > Budgets) to check your configured alert thresholds. Three defaults are pre-configured at 75%, 90%, and 100% of your annual commitment.
If Account Management already answers your question, you're done and can skip the rest of this tutorial. If not, continue to the next steps to learn where DQL can help you:
| Need | Account Management | DQL |
|---|---|---|
Capability-level forecast | No | Yes |
Cost center or team-level breakdown | No | Yes |
30/60/90-day scenario table | No | Yes |
Days until a specific threshold fires | No | Yes |
Establish how much Full-Stack Monitoring costs per day on average and project that 30 days forward.
Run this query:
fetch dt.system.events, from: -30d| filter event.kind == "BILLING_USAGE_EVENT"| filter event.type == "Full-Stack Monitoring"| dedup event.id| fieldsAdd day = bin(timestamp, 1d)| summarize daily_gib_hours = sum(billed_gibibyte_hours), by: {day}| summarize avg_daily_gib_hours = avg(daily_gib_hours)| fieldsAdd avg_daily_cost_usd = avg_daily_gib_hours / 100000.0 * 1000| fieldsAdd projected_30d_cost_usd = avg_daily_cost_usd * 30| fields avg_daily_gib_hours, avg_daily_cost_usd, projected_30d_cost_usd
The result is a single row:
| avg_daily_gib_hours | avg_daily_cost_usd | projected_30d_cost_usd |
|---|---|---|
48,200 | $482.00 | $14,460.00 |
projected_30d_cost_usd is your flat run-rate baseline, with no growth assumed. Use it as the floor for the scenario table in Step 4.
If your fleet changed recently (hosts onboarded, decommissioned, or switched monitoring mode), the 30-day average will be diluted. Change from: -30d to from: -7d to use only the post-change baseline.
| dedup event.id is mandatory in every billing query. Dynatrace refreshes metering records when correcting measurements. Without it, the same consumption period is counted multiple times and figures appear 10–30% higher than they are.
Is consumption flat or growing? Compare the current week to the previous week to find out.
Run this query:
fetch dt.system.events, from: -14d| filter event.kind == "BILLING_USAGE_EVENT"| filter event.type == "Full-Stack Monitoring"| dedup event.id| fieldsAdd week = if(timestamp >= now() - 7d, "current", else: "previous")| summarizecurrent_gib_hours = sum(if(week == "current", billed_gibibyte_hours, else: 0.0)),previous_gib_hours = sum(if(week == "previous", billed_gibibyte_hours, else: 0.0))| fieldsAdd growth_rate = (current_gib_hours - previous_gib_hours) / previous_gib_hours| fieldsAdd growth_pct = round(growth_rate * 100, decimals: 1)| fields previous_gib_hours, current_gib_hours, growth_pct
The result is a single row:
| previous_gib_hours | current_gib_hours | growth_pct |
|---|---|---|
320,100 | 377,700 | +18.0% |
Reading the result:
growth_pct below 5%: consumption is effectively flat; the Step 2 run-rate projection is a reliable estimate.growth_pct between 5–15%: moderate growth; run Step 4 to understand the trajectory.growth_pct above 15%: significant growth; continue to Steps 4 and 5 and consider setting a capability-scoped budget alert.A single week of growth is not a trend. Two consecutive weeks in the same direction is the minimum signal worth acting on.
Compound the growth rate forward to understand the 90-day trajectory. This query takes the current week as the weekly baseline and projects at 30, 60, and 90-day intervals.
Run this query:
fetch dt.system.events, from: -14d| filter event.kind == "BILLING_USAGE_EVENT"| filter event.type == "Full-Stack Monitoring"| dedup event.id| fieldsAdd week = if(timestamp >= now() - 7d, "current", else: "previous")| summarizecurrent_gib_hours = sum(if(week == "current", billed_gibibyte_hours, else: 0.0)),previous_gib_hours = sum(if(week == "previous", billed_gibibyte_hours, else: 0.0))| fieldsAdd growth_rate = (current_gib_hours - previous_gib_hours) / previous_gib_hours| fieldsAdd current_weekly_cost_usd = current_gib_hours / 100000.0 * 1000| fieldsAdd projected_30d_usd = current_weekly_cost_usd * pow(1.0 + growth_rate, toDouble(30) / 7.0)| fieldsAdd projected_60d_usd = current_weekly_cost_usd * pow(1.0 + growth_rate, toDouble(60) / 7.0)| fieldsAdd projected_90d_usd = current_weekly_cost_usd * pow(1.0 + growth_rate, toDouble(90) / 7.0)| fieldsgrowth_pct = round(growth_rate * 100, decimals: 1),current_weekly_cost_usd,projected_30d_usd,projected_60d_usd,projected_90d_usd
The result is a single row. The first column is the input; the remaining three are the projected costs.
Growth rate and current baseline:
| growth_pct | current_weekly_cost_usd |
|---|---|
+18.0% | $3,777 |
Projected spend:
| projected_30d_usd | projected_60d_usd | projected_90d_usd |
|---|---|---|
$19,100 | $28,300 | $41,900 |
Compare projected_90d_usd against your Full-Stack Monitoring budget alert threshold. If the projected value exceeds your threshold, that alert will fire before 90 days are up. Continue to Step 5 to calculate exactly when.
This is a scenario, not a forecast. The query assumes the current week's growth rate continues unchanged. Real-world consumption does not compound linearly. Host counts stabilize, deployments complete, auto-scaling settles. Use this to identify risk, not to predict an invoice.
Given a known budget threshold, calculate how many days remain at the current burn rate before Account Management sends the notification email.
Replace 5000.0 in the query with your Full-Stack Monitoring budget threshold. You can find your threshold in Budgets (Account Management > Subscription > Cost Management > Budgets).
fetch dt.system.events, from: -30d| filter event.kind == "BILLING_USAGE_EVENT"| filter event.type == "Full-Stack Monitoring"| dedup event.id| fieldsAdd day = bin(timestamp, 1d)| summarize daily_gib_hours = sum(billed_gibibyte_hours), by: {day}| summarize avg_daily_gib_hours = avg(daily_gib_hours)| fieldsAdd avg_daily_cost_usd = avg_daily_gib_hours / 100000.0 * 1000| fieldsAdd budget_threshold_usd = 5000.0| fieldsAdd days_until_alert = round(budget_threshold_usd / avg_daily_cost_usd, decimals: 0)| fields avg_daily_cost_usd, budget_threshold_usd, days_until_alert
The result is a single row:
| avg_daily_cost_usd | budget_threshold_usd | days_until_alert |
|---|---|---|
$482.00 | $5,000.00 | 10 days |
Use days_until_alert to decide what action is needed:
| Days remaining | Status | Action |
|---|---|---|
> 90 | On track | No immediate action needed. |
30–90 | Watch | Review with team; check if growth is expected. |
< 30 | Escalate | Engage account team; evaluate cost reduction levers. |
Budget alert thresholds in Account Management use your actual contracted costs, while this query uses list prices. The two numbers are directionally comparable but not identical. If no Full-Stack Monitoring budget exists yet, create one scoped to the relevant environment and capability. For more information, see Budget alerts.
Budget alerts in Account Management are evaluated daily after 12:00 UTC and fire once on the day a threshold is crossed. There is no intra-day alerting.
| Pitfall | Impact | Fix |
|---|---|---|
Missing | Usage figures appear 10–30% higher than reality. | Apply before every |
You can now forecast DPS spend beyond what Account Management shows out of the box. Specifically, you can:
filter event.type and the rate card divisor.