While building a file conversion and sharing app, my first implementation handled file conversion directly inside the API request.
It worked.
But as file sizes increased, requests stayed open for hundreds of milliseconds while the server was busy processing files.
The problem wasn't the conversion itself.
The problem was that users were waiting for work that didn't need to happen synchronously.
So I moved file conversion to BullMQ workers backed by Redis.
The flow became:
Upload → Job added to BullMQ → API responds immediately → Worker processes file → Status updated → User receives result
Why BullMQ worked better here:
- Faster API responses
- Request handling separated from heavy file processing
- Better scalability through worker concurrency
- Retries and failure handling built into the queue
- More predictable system behavior under load
Results from load testing
- API p95 latency reduced by 212x (800 ms → 3.8 ms)
- Throughput increased by 4.8x (1.3 → 6.2 requests/sec)
- Tested with 20 concurrent requests
Tradeoff:
- Additional infrastructure (Redis + workers)
- More operational complexity
- Eventual consistency instead of immediate completion
If every request needed an instant response, synchronous processing might still be the simpler choice.
This was a good reminder that performance improvements often come from moving work out of the critical request path rather than making the work itself faster.
Top comments (0)