Laravel 6 min read

When Laravel reports and CSV exports start timing out

Laravel reports or CSV exports timing out? I explain how to investigate slow queries, memory usage and background exports, then scope a reliable fix.

When Laravel reports and CSV exports start timing out

A report that worked when your Laravel application had a few hundred orders can become a daily nuisance once the business has years of records. Staff shorten the date range, download several files and stitch them together. Eventually someone asks whether you need a bigger server or a new system.

I would start with the report itself. A slow Laravel report or CSV export can involve the database, application memory, file generation or the way the request runs. Those need different fixes. Increasing a timeout before finding the bottleneck can leave people waiting longer for the same failure.

Describe one failing export precisely

The most useful starting point is a repeatable example: which report, which filters, which user role and what happens after clicking Export. Does the browser show an error? Does a file arrive with missing rows? Does the whole application slow down while it runs?

I would compare a small working range with the failing range and record elapsed time, memory usage, query behaviour and the number of records being processed. I would also establish whether the delay starts before file generation or during it. That turns “the reporting is slow” into something we can measure.

For business owners, a screenshot of the filters and the approximate time of a failure is enough to begin. There is no need to email a customer database or credentials with an initial enquiry.

Check what the database is being asked to do

A report might load every order, then fetch the customer, line items and payments separately for each one. Another might ask the database to sort a large result set before discarding most of it. The visible report can look simple while the work behind it grows considerably.

I would inspect the generated queries and their execution plans before choosing a change. That may lead to removing repeated lookups, fetching fewer columns, calculating totals in the database or adding an index suited to the actual filters. An index is something to justify against the query and workload, not something to add to every column that looks relevant.

The result still has to mean the same thing. A faster revenue total is not useful if a rewritten join counts an order twice. I would compare known records and totals before and after the change, including refunds and any other adjustments the report is supposed to include.

A large export should not need every record in memory at once

For detailed exports, I would check whether the code builds one enormous collection before writing the file. The query might finish quickly while the application struggles to hold and transform all its results.

Laravel's query builder documentation describes chunked and lazy processing, which can let an application work through results in smaller groups. The right approach depends on ordering, relationships and whether the underlying data can change during the export. I would use the documentation for the application's installed version when implementing it.

Reading records in batches is only part of the job. The file writer also needs checking: collecting every generated row in memory afterwards defeats the purpose. I would measure the full path from query to completed download.

Decide whether the user needs an immediate download

A small export can reasonably finish in the browser request. A substantial report may work better as a background task: the user requests it, carries on working and gets a download when it is ready.

That needs a complete user journey. I would include a visible requested or processing state, a clear failure message, an expiry policy for old files and a way to avoid starting the same expensive export repeatedly. Download access should be checked against the user and organisation entitled to the report.

Moving the work into a queue does not remove its resource requirements. Laravel's queue documentation covers worker timeouts and retries. These need to be configured for the application, and a retry should not append duplicate rows to a half-written file. I would also check that exports cannot hold up more urgent work such as customer notifications.

If jobs are not being picked up at all, my separate guide to investigating stuck Laravel queues covers that starting point.

Agree what “correct at the time of export” means

Suppose a sales export starts at 10:00 and an order is refunded while it runs. Should the file represent the position at 10:00, or include changes made during generation? There is no useful technical answer until the business requirement is clear.

I would agree the reporting period, timezone, status rules and treatment of later adjustments. For some operational lists, live data is fine. For a period-end report, a defined snapshot or reporting dataset may be appropriate. The chosen approach should make the result explainable to the person using it.

The same applies to caching a dashboard. Reusing a calculated total can be useful, but the interface should tell staff when it was updated. I would not quietly serve yesterday's figures under a label that implies they are current.

Test the change against the workload that caused the problem

A successful export of ten rows is not evidence that the month-end problem is fixed. I would test representative volumes in a suitable environment, then agree a controlled production check.

  • Compare record counts and totals with a trusted sample.
  • Exercise empty results, large date ranges and the roles that use the report.
  • Confirm users cannot download another organisation's file.
  • Check failure and retry behaviour for background exports.
  • Measure the effect on other requests while reports are running.
  • Record the runtime and memory changes, alongside any remaining limits.

Those checks also help decide whether a targeted repair is enough or whether reporting needs a separate design. I would make that decision from the workload, rather than assuming every slow export requires a rebuild.

Get the report back into a usable working day

I work on performance, reporting, data exports and inherited applications through my Laravel development and ongoing support service. A useful first scope is one report with a clear expected result and an agreed way to measure it.

Tell me what the report is used for, where it fails and whether the problem began after a change or grew gradually with the data. From there, I can help identify the investigation needed and scope the repair.

Is a Laravel report holding up your team?Send me the report name, the failing date range and what your staff need from the result. I can help investigate the bottleneck and scope a practical fix.
Discuss your Laravel report with Adam

Need a hand with this?

Work directly with me on an existing Laravel application, from a focused assessment to ongoing development.

A related project

Improving an existing Laravel application in place

Focused work on catalogue loading and operational screens, backed by regression checks for the workflows already in use.

Talk directly to Adam

Share this article

Back to Blog