Your support team is either understaffed or overstaffed right now. You just don't know which. Understaffing means SLA breaches, burned-out agents, and customers waiting too long. Overstaffing means wasted budget you could spend elsewhere. Your helpdesk export may help you estimate future ticket volume and the range of likely results. This analysis turns that history into a defensible forecast with prediction intervals you can hand to your VP when requesting headcount.
Worked Example (Simulated): Forecasting Next Week's Tickets
Question: Can past daily counts help plan shifts for the coming week?
Inputs: Simulated data, seed 17. The script makes 120 daily counts, from 2025-01-01 through 2025-04-30. It builds in a base of 32 tickets, a rise of 0.12 tickets per day, a weekday cycle, and random noise with a standard deviation of 4. It uses 105 days to fit the forecast and 15 days to compare forecasts with later counts.
Method: For each day of the week, the script takes the mean count from the fit set. It compares that forecast with a simple baseline: the mean count from the last 7 days. It measures mean absolute error (MAE), the average size of the miss, on the 15 later days. It then forecasts the next 7 days and prints, beside each forecast, the level the script's own rule gives for that day before noise.
from datetime import date, timedelta
from random import Random
from statistics import mean
SEED = 17
N_DAYS = 120
TRAIN_DAYS = 105
START = date(2025, 1, 1)
WEEKDAY_EFFECT = [-3, 1, 3, 2, 0, -4, -5]
TREND = 0.12
rng = Random(SEED)
counts = []
for t in range(N_DAYS):
weekday_effect = WEEKDAY_EFFECT[(START + timedelta(days=t)).weekday()]
count = round(32 + TREND * t + weekday_effect + rng.gauss(0, 4))
counts.append(max(0, count))
train = counts[:TRAIN_DAYS]
holdout = counts[TRAIN_DAYS:]
weekday_means = {
weekday: mean(
train[t]
for t in range(TRAIN_DAYS)
if (START + timedelta(days=t)).weekday() == weekday
)
for weekday in range(7)
}
weekday_predictions = [
weekday_means[(START + timedelta(days=TRAIN_DAYS + i)).weekday()]
for i in range(len(holdout))
]
baseline_value = mean(train[-7:])
baseline_predictions = [baseline_value] * len(holdout)
mae_weekday = mean(
abs(actual - predicted)
for actual, predicted in zip(holdout, weekday_predictions)
)
mae_baseline = mean(
abs(actual - predicted)
for actual, predicted in zip(holdout, baseline_predictions)
)
future_days = [START + timedelta(days=N_DAYS + i) for i in range(7)]
future_predictions = [weekday_means[day.weekday()] for day in future_days]
# What the rule that made the data gives for those days, before noise.
future_built_in = [
32 + TREND * (N_DAYS + i) + WEEKDAY_EFFECT[day.weekday()]
for i, day in enumerate(future_days)
]
print(f"Simulated data, seed {SEED}")
print(
f"Input: {N_DAYS} daily counts from {START} through "
f"{START + timedelta(days=N_DAYS - 1)}"
)
print(
f"Method: weekday mean; train={TRAIN_DAYS} days; "
f"holdout={len(holdout)} days"
)
print(f"Holdout MAE, weekday mean: {mae_weekday:.2f} tickets/day")
print(
"Holdout MAE, trailing 7-day mean baseline: "
f"{mae_baseline:.2f} tickets/day"
)
print("Next 7 dates: weekday-mean forecast, built-in level (no noise)")
for day, prediction, built_in in zip(
future_days, future_predictions, future_built_in
):
print(f"{day}: {prediction:.1f}, {built_in:.1f}")
print(f"Peak forecast: {max(future_predictions):.1f} tickets/day")
Printed output:
Simulated data, seed 17
Input: 120 daily counts from 2025-01-01 through 2025-04-30
Method: weekday mean; train=105 days; holdout=15 days
Holdout MAE, weekday mean: 6.27 tickets/day
Holdout MAE, trailing 7-day mean baseline: 3.40 tickets/day
Next 7 dates: weekday-mean forecast, built-in level (no noise)
2025-05-01: 39.4, 48.4
2025-05-02: 36.1, 46.5
2025-05-03: 35.8, 42.6
2025-05-04: 34.6, 41.8
2025-05-05: 35.6, 43.9
2025-05-06: 39.7, 48.0
2025-05-07: 39.9, 50.1
Peak forecast: 39.9 tickets/day
Result: The weekday forecast had a mean absolute error of 6.27 tickets per day. The recent-mean baseline had an error of 3.40. The weekday forecast lost on this holdout, and that is expected here. The script builds in a rise of 0.12 tickets per day. The weekday mean ignores that rise, so its forecasts lag. The recent mean follows the rise. For the same reason the next 7 forecasts (34.6 to 39.9) sit below the built-in level for those days (41.8 to 50.1). A forecast should be checked against a simple baseline before it is used to plan shifts.
Limit: These counts are simulated. A real helpdesk may not look like this, and one holdout does not show how a method will do on future data.
Sources: Hyndman and Athanasopoulos, Forecasting: Principles and Practice (3rd ed.), a textbook that covers simple baseline forecasts and forecast error measures.
Why Ticket Volume Forecasting Matters
Support operations run on a knife edge. Every agent-hour you over-schedule is money wasted. Every hour you under-schedule raises the risk of an SLA breach.
To see where your own measure is heading, with a likely range, try the free forecasting tool.
The problem isn't a lack of data. Zendesk, Freshdesk, Jira Service Management, and every other helpdesk tool can export daily ticket counts going back months or years. The problem is turning that data into a forecast that's more than "last month plus 10%." A forecast can help show patterns in past counts, but it may miss changes. Compare its error with a simple baseline on later data. A forecast that gives a range of likely outcomes, not a single number, helps you plan for a bad case.
When to Use Ticket Volume Forecasting
- Headcount requests: "We need two more agents next quarter" is an opinion. "Our model predicts 18% more tickets next quarter (95% CI: 12-24%), which requires 1.8 additional FTEs to maintain our 4-hour SLA" is a business case.
- Shift scheduling: match agent schedules to predicted volume by day of week. If Mondays consistently spike 40% above average, staff accordingly instead of spreading agents evenly across the week.
- Budget planning: forecast ticket volume for the next quarter or year to estimate support costs. Multiply predicted volume by your cost-per-ticket to build an accurate support budget.
- Post-launch planning: product launches, feature releases, and pricing changes create ticket surges. Use historical launch data to forecast how big the spike will be and how long it will last.
- SLA risk management: identify future weeks where predicted volume exceeds your team's capacity at current staffing levels. Fix the problem before it becomes a breach.
This analysis works best for teams handling a steady ticket stream. A high ticket count alone does not ensure an accurate forecast. Check the model's error on later counts before using it to plan staffing.
What Data Do You Need?
A basic file can have a date and a ticket count for each day or week.
Where to get it
- Zendesk: Explore > Queries > export ticket created dates, then pivot to daily counts
- Freshdesk: Reports > Helpdesk Productivity > export by day
- Jira Service Management: JQL export of created dates, then aggregate in Excel
- Any helpdesk: export raw tickets with created_date, then create a pivot table counting tickets per day
Required columns
- date: daily or weekly dates (2024-01-15, 1/15/2024, Jan 15 2024 all work)
- ticket_count: integer count of tickets created that day or week
How much history?
- Longer history lets a forecast pick up seasonal patterns such as holiday surges and summer slowdowns.
- Weekly data: works fine.
If you're tracking ticket volume by category or channel (billing vs. technical, email vs. chat), you can run separate forecasts for each. This is especially valuable if different channels have different seasonality: chat might spike during business hours while email accumulates overnight.
How to Read the Report
Forecast chart: the centerpiece of the report. Your historical data appears as a solid line, then extends into the future with predictions surrounded by two shaded bands. The darker band is the 80% prediction interval (if the model's assumptions hold, about 4 out of 5 times actual volume will land inside this range). The lighter band is the 95% interval. For staffing, plan capacity for the upper edge of the 80% band. That covers most scenarios without over-investing in headcount for the extreme tail.
Seasonal decomposition: breaks your ticket data into three layers: trend (are tickets growing over time?), seasonal (which days or months are consistently high or low?), and residual (random noise the model can't explain). The seasonal component is gold for scheduling. If the model shows Mondays are 35% above average and Fridays are 20% below, that's a permanent staffing pattern you should bake into your schedules.
Model diagnostics: the report runs the Ljung-Box test on residuals to verify the model isn't missing important patterns. For practical purposes, look at the MAPE (Mean Absolute Percentage Error) as a rough guide. Check forecast error on data the model did not use, and compare it with a simple baseline. A high error suggests your ticket volume has high randomness, so the exact numbers have wider uncertainty.
AI insights: plain-language interpretation of the forecast, highlighting growth rate, seasonal peaks, and any trend changes. This is the section you paste into a slide when presenting to leadership.
What to Do With the Results
Immediate
- Compare forecast to current staffing: divide predicted daily volume by your target tickets-per-agent to calculate required headcount for each future week
- Identify gap weeks: flag any weeks where predicted volume exceeds your team's capacity. These are your SLA risk windows.
- Adjust schedules: use the seasonal pattern to redistribute agent shifts. Move coverage from consistently quiet days to consistently busy ones.
Strategic
- Run monthly: re-run the forecast each month with updated data. As your team grows or your product changes, the patterns shift. Monthly updates keep your staffing aligned.
- Build your headcount case: use the 3-month or 6-month forecast to project when you'll need additional agents, and bring the forecast chart to your budget conversation.
- Measure deflection impact, if you launch a knowledge base or chatbot, re-run the forecast 60 days later. If actual volume falls below the pre-intervention forecast, that's your deflection ROI.
When to Use Something Else
- Just want to see the trend: If you don't need prediction intervals or a formal forecast (just "are tickets going up or down?") use a simple trend analysis. It's faster and the output is easier to explain in a standup.
- Want to forecast by category: Run separate ARIMA forecasts for each ticket category. Upload one CSV per category and compare the forecasts side by side.
- Tickets driven by external events: If volume is dominated by unpredictable events (outages, viral social media posts), ARIMA will underperform because time series models learn from patterns, not one-off shocks. Consider building scenario-based staffing plans instead.
Your turn
Bring your own data and the question you actually need answered.
MCP AnalyticsData science by email Send us your data and your question, and we will reply. ds@mcpanalytics.ai