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)