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(); }); }
๐ Explanation:
-
Cache::remember
stores the result untilendOfDay()
. - 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.']); }
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) } }
Step 3: Show Download Button Only When File is Ready
Instead of loading the entire data on client side:
- 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]); }
- 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 } };
โ 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)