Asynchronous tasks and Celery: processing time-consuming background tasks
📂 Stage: Stage 5 - Advanced Advancement (Performance and Architecture) 🔗 Related chapters: Redis 集成 · RESTful API 开发
0. A real jamming scene
When uploading a profile picture to the blog backend last week, I conveniently uploaded a 12MB HEIC photo taken with an iPhone (converted to PNG and submitted). As a result, the front-end icon rotated for more than 3 seconds before I got the save link. I almost thought the interface was down. After checking the logs, I found that the culprit was PIL image compression - it took a full 2.8 seconds to process this image.
In fact, there are similar "time assassins" hidden in many web requests: compressing images, sending emails, exporting reports, calling third-party APIs... Once these operations are executed synchronously, the user will experience endless loading, and server resources will be slowly consumed.
The standard approach to solving this problem is to introduce asynchronous task queue Celery.
1. Core idea: Turn "waiting for others" into "return first, work later"
To sum it up in one sentence: Split the synchronous process of "the user must wait for the result" into an asynchronous process of "immediately return the acceptance receipt and work secretly in the background".
Taking the image upload mentioned earlier as an example, the modified process is as follows:
Compared with before the transformation, the change in experience is: From "waiting for 3 seconds" to "receiving submission feedback within 100ms"; for the server, the web process can be released immediately to process the next request, and will not be overwhelmed by blocked time-consuming tasks.
2. Infrastructure construction
We choose Redis to serve as both message middleware (Broker) and result storage (Backend). The reason is very practical: most projects already use Redis for caching, and there is no need to introduce RabbitMQ or Kafka separately for Celery, which will only increase maintenance complexity.
2.1 Install dependencies
Install directly in the virtual environment:
(pillowandflask-mailIt is an additional library used in this example, increase or decrease as needed)
2.2 Minimize Celery configuration
Newapp/celery_app.py, separating the Celery instance can not only avoid circular imports, but also facilitate the management of the production environment:
3. Write reusable background tasks
Celery tasks are essentially adding a decorator to ordinary functions. We can extract common time-consuming operations into independent task modules.
3.1 Image compression task
Newapp/tasks/image_tasks.py, with necessary fault-tolerance logic, such as processing damaged pictures, cleaning up failed deletions, etc.:
3.2 Send welcome email
Newapp/tasks/mail_tasks.py. Note that the Worker process and the Web process are separated, so when using extensions that require application context such as Flask-Mail, you must manually activate:
4. Call tasks in Web routing
Calling Celery tasks** cannot be usedfunction()**, so use:
function.delay()— Simplified version, only supports positional parameters and keyword parametersfunction.apply_async()— Full version, you can set countdown, retry strategy, specify queue, etc.
4.1 Submit compression task
Suppose there is an upload blueprintapp/routes/upload.py:
4.2 Query task status
After the front end gets the task ID, it can poll the following interface every 200ms~1s:
5. Start the Celery service
Remember: Worker and Web processes must be started separately and cannot be squeezed into the same terminal.
5.1 Development environment
-ASpecify the Celery instance location (will automatically findcelery_app)--loglevel=infoOutput details to facilitate debugging--concurrency=2Start 2 Worker processes (generally set to 1 to 2 times the number of CPU cores)
5.2 Production environment
The production environment cannot be started directly from the terminal. It is recommended to use systemd (Linux) or Docker for daemonization. Here is a simple Docker Compose configuration snippet:
6. Core process shorthand
A minimalist checklist to help you remember the entire process in your mind:
7. Situation Suitability & Pitfall Avoidance Guide
✅ It is strongly recommended to perform background tasks in scenarios
- Picture, video, audio and other media processing
- Batch data export (Excel, PDF)
- Send notifications such as emails, text messages, and push notifications
- Third-party API calls that take more than 1 second
- Background statistics, data cleaning and other scheduled tasks
❌ Do not use background tasks in scenarios
- Operations that must return results immediately (such as login verification, simple queries)
- An operation with extremely simple logic and time-consuming < 50ms (submitting to Redis itself also has overhead)
🔗 Extended reading

