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)