The report that took six minutes at quarter end
A headcount report that had returned in under a minute all year took six minutes on the first working day of April, and by the second week it stopped returning at all. The HR business partner who owned it had changed nothing. A January project had swapped the report onto a broader worker data source, so it now read every worker record in the tenant before filtering down to one supervisory organisation.
Finding that took two days because everyone started with the columns. Column count is the least expensive part of most Workday HCM reports. The expensive decisions are made before a single column is chosen, in the data source and whether the filters apply during retrieval or after.
Report performance here is a short list of decisions repeated across hundreds of reports, and most slow ones are slow for the same reason. They fetch far more than the question needs and throw most of it away.
The data source decides most of the work
Every custom report starts by choosing a data source, and that choice sets the ceiling for everything after it. An indexed source that already narrows to a population, such as workers in a supervisory organisation as of a date, hands back a small set with the filtering done. A broad source returns all workers and all of their history, and your filters run over that result after it arrives.
The difference shows up as an order of magnitude rather than a few seconds. A report filtered at the source touches the rows it needs. The same report on a broad source touches every row in the tenant, evaluates the filter on each one, discards most of them, then repeats the per-row work for every related object and calculated field on what is left.
So the first question on any slow report is which data source it uses and whether a narrower indexed one answers the same question. Workday ships a lot of them with confusingly similar names, and the person who built the report usually picked the first one holding the fields they recognised. Moving to a better source means rebuilding the filters, which is real work and still the cheapest fix available.
A prompt only helps if the source can use it
Prompts are the second decision and the one most often misread. A prompt the data source can filter on reduces what gets retrieved. A prompt on a field the source cannot filter on, or on a calculated value, gets applied after retrieval. The user sees a smaller result either way, so nobody notices the difference until the report times out.
Two reports can be identical on screen and minutes apart in how they run. The first prompts on an attribute the source understands, such as the organisation or the effective date. The second prompts on a value that must be produced for every row before it can be evaluated, and it gets slower every time the worker population grows.
When I take over a slow report I run it twice, once with the widest prompt values anyone uses and once with the narrowest. If the run time barely moves, the prompt is trimming the output rather than reducing the fetch.
The row count nobody checks
Look at how many rows the report returns. That number explains most complaints and almost nobody writes it down. A manager asks about the eleven people on their team with a compensation change pending. The report retrieves forty thousand worker rows, evaluates six calculated fields on each, and returns eleven.
That shape is the normal shape of the problem. Reports get built by starting from everything available and narrowing in the output instead of the retrieval. The eleven rows on screen tell the requester the report is small. The run time says otherwise, and that gap is the diagnosis.
Ask what the answer should look like before asking why the report is slow. If the question concerns a dozen workers and the report reads the tenant to find them, no column tuning will help. The same discipline applies to making the analytics question a requirement instead of a discovery made after the build.
Every hop and every calculation is paid per row
Related business objects are where reports quietly double. A worker row that also needs the manager's name, the manager's location and the cost centre hierarchy is three traversals for every row in the result. Each hop is cheap on one record and costly across forty thousand, and nothing in the definition says which columns cost a traversal.
Calculated fields are charged the same way. One is evaluated once for every row returned, and one that traverses a relationship of its own runs once per row per hop. A nested field reaching through two related objects to compare two dates runs forty thousand times to answer a question about eleven people. There is a separate guide on calculated fields that multiply; the performance point here is that cost scales with rows.
Moving a calculation out of the report changes when the cost is paid rather than removing it. A value maintained on the worker record by a business process, or written overnight by an integration, costs nothing at report time. That is often the right trade, and it belongs in the design review, because the team running that overnight process now owns part of the report's behaviour.
The same report is slower for the person who reported it
Report results are filtered by what the person running the report is allowed to see, so the same report legitimately performs differently for different people. A recruiter constrained to one region and an HR director with tenant-wide access push very different amounts of work through one definition.
Testing with an administrator account hides that entirely. Administrators hold the broadest security groups in the tenant, so your timing describes the largest population the report can reach and not the run the manager complained about. Reproduce it under their access in a sandbox, or ask them to run it while you time it. Security group sprawl makes that harder, because nobody can say quickly what one user sees.
Measure before you change anything. Record the run time, the row count returned, the data source, the prompt values and who ran it. Change one thing, run it the same way, and put the new numbers beside the old. Half the reports handed to me as performance problems turn out to be a number nobody can reproduce twice, timed once during a payroll close.
- The data source, and whether a narrower indexed source answers the same question.
- Each prompt, and whether the source applies it or the report applies it afterwards.
- Rows returned, set against the number of rows the question actually needs.
- How many related business objects it reaches into, and whether every hop still earns a column.
- Which calculated fields are evaluated per row, and which of those traverse a relationship.
- Who reported it, what their security groups allow, and the run time under their access rather than yours.
- Whether anyone has timed it twice with the same prompt values.
Heavy reports belong on a schedule
Some reports are as fast as they are going to get and still take minutes. Once a report retrieves only what it needs, the remaining decision is when it runs. Schedule it overnight, deliver the output to a notification or a secure drop, and let people read a result produced while nobody waited. Keep interactive runs for questions people need answered in seconds.
Scheduling also gives you the measurement you were missing, because the run history records a duration for every execution under the security the schedule runs with. Over a few weeks that history shows whether the report is drifting slower as the population grows, the failure that arrives without anyone changing anything.
Some requests have outgrown reporting altogether. A monthly pull of every worker with forty columns, going to a downstream system or a finance spreadsheet, is an extract. Build it as an integration with a schedule and a delivery target, or move the question into a warehouse where that shape of data belongs. Saying so early beats tuning a report that was never going to satisfy it.
Pick the report your service desk hears about most often, open its definition, and write down two things. The data source it uses, and the rows it returns on an average run. If that row count is many times larger than the answer anybody wanted, you have found the work, and it sits in the source and the prompts rather than the columns.



