🚀 Implementing a Download Audio Job in Production: Best Practices and Lessons Learned
When building modern applications—whether it's for media streaming, transcription, or podcast distribution—supporting asynchronous audio downloads is essential. In a production environment, handling audio files efficiently, securely, and without blocking user experience requires a background job system.
In this post, I’ll walk you through how we implemented a DownloadAudio
job in production, our tech stack, the workflow, and the key lessons we learned.
đź§° Tech Stack
Before diving in, here's what we used:
- Laravel 10 (PHP Framework)
- Redis (Queue driver)
- Supervisor (Process monitor for running Laravel workers)
- DigitalOcean (Production server)
- Amazon S3 / Local Storage for audio file storage
🎯 The Goal
We wanted a system where:
- The user submits an audio URL or audio identifier.
- The system queues a
DownloadAudio
job. - The job downloads the audio in the background and stores it.
- A notification or status update is sent once the download is complete or fails.
🛠️ Implementation
Step 1: Create the Job Class
bash
php artisan make:job DownloadAudio
Step 2: Define the Job Logic
php
Copy
Edit
public function handle()
{
try {
$audioUrl = $this->audio->source_url;
$fileName = Str::slug($this->audio->title) . '.mp3';
$contents = file_get_contents($audioUrl);
Storage::disk('public')->put("audios/{$fileName}", $contents);
$this->audio->update([
'file_path' => "audios/{$fileName}",
'status' => 'downloaded',
]);
Log::info("Downloaded audio: {$fileName}");
} catch (\Exception $e) {
Log::error('Download failed: ' . $e->getMessage());
$this->audio->update(['status' => 'failed']);
}
}
Step 3: Dispatch the Job
php
Copy
Edit
DownloadAudio::dispatch($audioInstance);
⚙️ Background Worker in Production
1. Configure the Queue Driver
In .env:
env
Copy
Edit
QUEUE_CONNECTION=redis
2. Setup Supervisor
ini
Copy
Edit
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/your-app/artisan queue:work redis --sleep=3 --tries=3 --timeout=90
autostart=true
autorestart=true
user=www-data
numprocs=1
redirect_stderr=true
stdout_logfile=/var/www/your-app/storage/logs/worker.log
Run these commands:
bash
Copy
Edit
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start laravel-worker:*
âś… Tips for a Smooth Production Rollout
Validate URLs before dispatching jobs.
Set timeouts for downloads—especially for large audio files.
Log everything, and use a Log Viewer if necessary.
Clean up failed jobs regularly to avoid filling up Redis.
Notify users of status (via email, notification, etc.) if necessary.
📊 Monitoring & Observability
Use Laravel Horizon if using Redis queues heavily.
Implement health checks for queue workers.
Store job logs separately from the main application logs.
đź’ˇ Lessons Learned
Permission issues are common in production—check storage and log directory permissions.
Jobs should be idempotent — a job should be able to fail and retry safely.
Separate logic and side effects — keep your job focused and offload notifications or further processing to other jobs/events if needed.
đź§© Conclusion
The DownloadAudio job is a great example of how background processing can improve your app's performance and user experience. By moving intensive tasks away from the main thread and handling them in the background, we make our systems more scalable and responsive.
Top comments (0)