DEV Community

Cover image for Efficient Reporting: Query Caching and Big Data Report Generation with Queues
Tahsin Abrar
Tahsin Abrar

Posted on

Efficient Reporting: Query Caching and Big Data Report Generation with Queues

Hey devs ๐Ÿ‘‹,

Today, letโ€™s discuss a real-world problem every backend developer faces at some point โ€“ optimizing heavy reports. We will explore:

โœ… How to cache report queries with fixed timelines
โœ… How to generate big data reports efficiently using job queues and handle downloads without overwhelming your client-side app.

Letโ€™s break it down step by step.


1. ๐Ÿ—“๏ธ Report Query Caching with Fixed Timelines

Imagine you have a dashboard where users frequently request a report of, say, the last 30 days sales data. Running the same heavy query every minute is inefficient.

๐Ÿ”‘ Solution: Cache the query result with a fixed timeline.

Why Fixed Timeline?

If you use indefinite cache expiry (like โ€œcache for 60 minutesโ€), the dataโ€™s freshness will differ based on the request time. A fixed timeline ensures:

  • All users see the same cached data within the period.
  • Cache expires at a known time (e.g., every day at 12:00 AM), keeping data consistency predictable.

How to Implement

Hereโ€™s a quick Laravel example using the cache facade:

use Illuminate\Support\Facades\Cache; public function getReport() { $cacheKey = 'sales_report_daily'; $expiresAt = now()->endOfDay(); // Cache expires at 11:59 PM today return Cache::remember($cacheKey, $expiresAt, function () { // Your heavy DB query here return DB::table('sales') ->whereDate('created_at', '>=', now()->subDays(30)) ->get(); }); } 
Enter fullscreen mode Exit fullscreen mode

๐Ÿ“ Explanation:

  • Cache::remember stores the result until endOfDay().
  • Next requests within the same day will fetch from cache, saving DB processing.
  • At midnight, the cache expires and the first request refreshes it.

๐Ÿ”ง Alternative use cases: weekly expiry (use endOfWeek()), monthly expiry, etc.


2. ๐Ÿ’พ Big Data Report Generation Using Job Queues

When dealing with big reports (e.g. millions of rows), running them in real-time and returning in the same request is impractical. It can crash your server or timeout your API gateway.

Best Practice:

โœ… Offload report generation to a queue job
โœ… Generate a downloadable file (CSV, Excel) in the background
โœ… Notify user when itโ€™s ready to download

Step-by-Step Implementation

Step 1: Trigger Report Job

Create an API endpoint or button action that dispatches a job to queue:

public function requestReport() { $user = auth()->user(); GenerateBigReport::dispatch($user->id); return response()->json(['message' => 'Report generation started. You will be notified once it is ready.']); } 
Enter fullscreen mode Exit fullscreen mode

Step 2: Build The Job

use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Support\Facades\Storage; class GenerateBigReport implements ShouldQueue { use Queueable; public $userId; public function __construct($userId) { $this->userId = $userId; } public function handle() { $data = DB::table('transactions')->get(); // Example: big dataset $csv = fopen(storage_path("app/reports/report_{$this->userId}.csv"), 'w'); // Add headers fputcsv($csv, ['id', 'amount', 'date']); foreach ($data as $row) { fputcsv($csv, [$row->id, $row->amount, $row->created_at]); } fclose($csv); // Optional: Notify user (email, notification) } } 
Enter fullscreen mode Exit fullscreen mode

Step 3: Show Download Button Only When File is Ready

Instead of loading the entire data on client side:

  1. Check if report exists:
 public function checkReport() { $path = "reports/report_" . auth()->id() . ".csv"; if (Storage::exists($path)) { return response()->json([ 'ready' => true, 'download_url' => Storage::url($path), ]); } return response()->json(['ready' => false]); } 
Enter fullscreen mode Exit fullscreen mode
  1. In your frontend:
const checkReport = async () => { const res = await fetch('/api/check-report'); const data = await res.json(); if(data.ready){ // show download button with data.download_url } else { // show "Processing..." or disabled button } }; 
Enter fullscreen mode Exit fullscreen mode

โœ… Benefits:

  • Users do not wait for heavy API responses
  • Server resources are used optimally via queued background processing
  • Client side remains performant without loading all big data in-browser

โœจ Final Thoughts

Using fixed timeline caching and job queues for big data reports are powerful techniques to build scalable applications.

๐Ÿ”ง Quick recap:

  • Cache reports smartly with fixed expiry for consistent freshness.
  • Generate big data reports asynchronously with queues.
  • Serve the final file as a download โ€“ never load huge datasets directly on the client side.

Top comments (0)