Which clients generate billable hours, which ones consume overhead, and where non-billable time is leaking margin. Generated by AI via Proxuma Power BI MCP server.
Which clients generate billable hours, which ones consume overhead, and where non-billable time is leaking margin. Generated by AI via Proxuma Power BI MCP server.
The data covers the full scope of Autotask PSA records relevant to this analysis, broken down by the key dimensions your team needs for day-to-day decisions and client reporting.
Who should use this: Account managers, MSP owners, and service delivery leads
How often: Monthly for client reviews, quarterly for QBRs, on-demand when client signals change
Which clients generate billable hours, which ones consume overhead, and where non-billable time is leaking margin. Generated by AI via Proxuma Power BI MCP server.
EVALUATE ROW(
"TotalHours", SUM(BI_Autotask_Time_Entries[hours_worked]),
"Billable", SUM(BI_Autotask_Time_Entries[Billable Hours]),
"NonBillable", SUM(BI_Autotask_Time_Entries[Non billable Hours]),
"BillableRatio",
DIVIDE(
SUM(BI_Autotask_Time_Entries[Billable Hours]),
SUM(BI_Autotask_Time_Entries[hours_worked])
),
"ClientsWithTime",
CALCULATE(
DISTINCTCOUNT(BI_Autotask_Time_Entries[company_id]),
NOT(ISBLANK(BI_Autotask_Time_Entries[company_id]))
)
)
Portfolio-wide split of billable vs non-billable hours across all clients and internal time
DEFINE
VAR ClientData =
ADDCOLUMNS(
SUMMARIZECOLUMNS(
BI_Autotask_Time_Entries[company_id],
"Hours", SUM(BI_Autotask_Time_Entries[hours_worked]),
"Billable", SUM(BI_Autotask_Time_Entries[Billable Hours])
),
"Ratio", DIVIDE([Billable], [Hours])
)
VAR WithBand =
ADDCOLUMNS(
FILTER(ClientData, [Hours] > 0 && NOT(ISBLANK([company_id]))),
"Band",
SWITCH(TRUE(),
[Ratio] >= 0.95, "A: Elite (95%+)",
[Ratio] >= 0.85, "B: Strong (85-95%)",
[Ratio] >= 0.70, "C: Standard (70-85%)",
[Ratio] >= 0.50, "D: Low (50-70%)",
"E: Poor (<50%)")
)
EVALUATE
GROUPBY(WithBand, [Band],
"Clients", COUNTX(CURRENTGROUP(), [company_id]),
"Hours", SUMX(CURRENTGROUP(), [Hours]),
"Billable", SUMX(CURRENTGROUP(), [Billable]))
ORDER BY [Band]
Top 15 clients by total hours worked, with segmented bars showing the billable vs non-billable split per client
| Client | Total hours | Billable | Non-billable | Billable ratio |
|---|---|---|---|---|
| Craig-Huynh | 4,370 | 3,792 | 578 | 86.8% |
| Little Group | 3,791 | 3,127 | 665 | 82.5% |
| Lewis LLC | 2,801 | 2,665 | 136 | 95.2% |
| Martin Group | 2,217 | 1,970 | 247 | 88.8% |
| Wall PLC | 1,697 | 1,665 | 32 | 98.1% |
| Rivers, Rogers and Mitchell | 1,662 | 0 | 1,662 | 0.0% |
| Burke, Armstrong and Morgan | 1,312 | 1,096 | 216 | 83.5% |
| Ramos Group | 1,171 | 1,114 | 57 | 95.1% |
| Thompson, Contreras and Rios | 1,006 | 853 | 153 | 84.8% |
| Wu-Jackson | 962 | 916 | 46 | 95.2% |
| Doyle-Contreras | 962 | 954 | 8 | 99.1% |
EVALUATE
TOPN(12,
FILTER(
ADDCOLUMNS(
SUMMARIZECOLUMNS(
BI_Autotask_Time_Entries[company_id],
BI_Autotask_Time_Entries[company_name],
"Hours", SUM(BI_Autotask_Time_Entries[hours_worked]),
"Billable", SUM(BI_Autotask_Time_Entries[Billable Hours]),
"NonBillable", SUM(BI_Autotask_Time_Entries[Non billable Hours])
),
"BillableRatio", DIVIDE([Billable], [Hours])
),
NOT(ISBLANK(BI_Autotask_Time_Entries[company_id]))
),
[Hours], DESC
)
ORDER BY [Hours] DESC
Hours logged with no billable output: internal overhead and accounts running exclusively non-billable time
| Client | Total hours | Billable hours | Non-billable |
|---|---|---|---|
| Rivers, Rogers and Mitchell | 1,662 | 0 | 1,662 |
EVALUATE
FILTER(
ADDCOLUMNS(
SUMMARIZECOLUMNS(
BI_Autotask_Time_Entries[company_id],
BI_Autotask_Time_Entries[company_name],
"Hours", SUM(BI_Autotask_Time_Entries[hours_worked]),
"Billable", SUM(BI_Autotask_Time_Entries[Billable Hours]),
"NonBillable", SUM(BI_Autotask_Time_Entries[Non billable Hours])
),
"BillableRatio", DIVIDE([Billable], [Hours])
),
[Hours] > 50 && (ISBLANK([Billable]) || [BillableRatio] < 0.50)
)
ORDER BY [NonBillable] DESC
Clients with the most non-billable hours on their accounts (excluding internal and Rivers). These hours may represent missed billing, scope creep, or process gaps.
EVALUATE
TOPN(10,
FILTER(
ADDCOLUMNS(
SUMMARIZECOLUMNS(
BI_Autotask_Time_Entries[company_id],
BI_Autotask_Time_Entries[company_name],
"Hours", SUM(BI_Autotask_Time_Entries[hours_worked]),
"NonBillable", SUM(BI_Autotask_Time_Entries[Non billable Hours])
),
"NonBillShare", DIVIDE([NonBillable], [Hours])
),
[Hours] > 20 && NOT(ISBLANK(BI_Autotask_Time_Entries[company_id]))
),
[NonBillable], DESC
)
ORDER BY [NonBillable] DESC
The portfolio-wide billable ratio of 75.6% means roughly one in four hours logged does not generate revenue. That is within the typical MSP range of 70-80%, but there is room to improve.
The biggest factor is internal overhead. The null-company bucket accounts for 7,264 hours, and Rivers adds another 1,662 hours at 0% billable. Together, these two entries represent 8,926 hours, or 17.6% of all time logged. If Rivers is truly an internal monitoring account, it should be reclassified so it does not skew client-level metrics. If it is a paying client, someone needs to investigate why every single hour is flagged non-billable.
Foster Inc stands out as the highest-leakage client account. At 82.5% billable, they have 664 non-billable hours on the books. That is 3.4 full-time equivalent weeks of work that generated no revenue. Patterson Hood Perez is close behind with 578 non-billable hours. For both accounts, the question is whether those hours represent legitimate non-billable work (onboarding, project scoping, internal meetings) or time entries that should have been billed.
On the other end, Clements (99.3%), Client K (99.1%), and Wall PLC (98.1%) are running near-perfect billability. These accounts have tight processes, minimal overhead, and clean time tracking. They are the benchmark your other accounts should target.
The gap between the best client (Clements at 99.3%) and the lowest true client (Foster Inc at 82.5%) is 16.8 percentage points. Closing even half of that gap for the bottom performers would recapture hundreds of billable hours.
5 priorities based on the findings above
Foster Inc has the lowest billable ratio among active client accounts at 82.5%. Pull the time entries flagged as non-billable and categorize them: which are legitimate (internal meetings, project scoping) and which should have been billed? At typical MSP rates, 664 unbilled hours could represent $50,000-$100,000 in missed revenue. Start with the largest time entries and work backward.
Rivers has logged 1,662 hours with zero billable output. If this is an internal monitoring or infrastructure account, reclassify it so it does not appear in client-level reporting. If Rivers is a paying client, you have a serious billing gap. Either way, this needs an answer this week, not next quarter.
Internal time (no client assigned) accounts for 7,264 hours, or 14.3% of all time logged. Industry benchmarks for well-run MSPs target 10-12% internal overhead. Review the types of internal tasks consuming the most time. Are there recurring meetings that could be shorter? Administrative tasks that could be automated? Training that could be batched more efficiently?
Patterson Hood Perez is the largest client by hours (4,370) with 578 non-billable. At 86.8% billable, they are above the portfolio average, but the absolute number of unbilled hours is high. Check whether a specific project or recurring task is driving this. Even a 5% improvement would recover around 220 billable hours.
Clements at 99.3% and Wall PLC at 98.1% show that near-perfect billability is achievable. Study what makes these accounts different. Is it the contract structure? The way time entries are logged? The type of work being done? Apply those patterns to accounts below 90% and measure the improvement over the next quarter.
Autotask PSA tracks every time entry your team logs, including whether the entry is flagged as billable or non-billable. Proxuma Power BI pulls these entries through the Autotask connector and calculates the [Billable Hours] and [Non billable Hours] measures. The AI then runs DAX queries to group results by company and compute ratios.
A billable hour is any time entry in Autotask PSA where the billable flag is set. This typically includes client-facing work: ticket resolution, project tasks, and scheduled maintenance covered by contract. Non-billable hours include internal meetings, training, administrative tasks, and time logged against internal accounts.
Most MSPs operate between 65-80% billable at the portfolio level. Top-performing MSPs target 80%+ for individual client accounts. The internal overhead portion (time with no client) should stay below 12-15%. Per-client ratios above 90% indicate tight operations and clean time tracking.
Accounts with 0% billable are typically internal accounts (no client assigned) or monitoring/infrastructure accounts where all time is logged as non-billable by design. If a paying client shows 0%, it usually means the billable flag is misconfigured on their time entries or their contract type does not trigger billable tagging in Autotask.
Yes. The DAX queries in this report use all available data by default. You can add a date filter on BI_Autotask_Time_Entries[date_worked] to scope the report to a specific quarter, month, or custom range. Filtering to the last 90 days gives a more actionable picture for operational decisions.
Yes. Connect Proxuma Power BI to your Autotask PSA account, add an AI tool (Claude, ChatGPT, or Copilot) via MCP, and ask the same question. The AI writes the DAX queries, runs them against your real data, and produces a report like this in under fifteen minutes.
Connect Proxuma Power BI to your PSA, RMM, and M365 environment, use an MCP-compatible AI to ask questions, and generate custom reports - in minutes, not days.
See more reports Get started