Working outside of request context error with Celery background task
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
The "Working outside of request context" error in Flask + Celery occurs when a Celery task tries to access request, session, g, or other request-scoped objects. Celery tasks run in a separate worker process with no HTTP request, so Flask's request context does not exist. The fix is to pass all needed data as task arguments instead of accessing the request inside the task. If you need current_app (for config or extensions), use app.app_context() to create an application context inside the task.
The Error
Fix 1: Pass Data as Arguments (Recommended)
Extract all needed data from the request in the Flask route and pass it to the task:
Fix 2: Application Context for current_app
If the task needs Flask app configuration or extensions (database, mail):
Fix 3: Flask Factory Pattern
For applications using the factory pattern:
Fix 4: Manual App Context
This is simpler but creates a new app instance per task, which is less efficient.
What You Cannot Do in a Celery Task
Task Status Checking
Common Pitfalls
- Accessing
request,session, orginside a Celery task: Celery tasks run in a separate worker process with no HTTP request. There is no request context. Always pass needed data as function arguments from the Flask route handler. - Confusing application context with request context:
app.app_context()provides access tocurrent_appand app-level extensions (SQLAlchemy, Mail), but NOT torequestorsession. These are separate contexts. You can create an app context in a task, but never a request context. - Passing non-serializable objects as task arguments: Celery serializes task arguments (default JSON). Passing Flask
requestobjects, file handles, or SQLAlchemy model instances fails. Pass primitive types (strings, ints, dicts) and re-query the database inside the task. - Not running the Celery worker with the Flask app context: If you skip the
ContextTaskbase class, tasks that usedb.sessionorcurrent_app.configfail. Always configure Celery to wrap tasks inapp.app_context(). - Creating a new Flask app instance in every task call: While
app = create_app()inside a task works, it creates a new app and re-initializes all extensions on every task execution. Use theContextTaskbase class pattern to reuse a single app instance across all tasks in the worker.
Summary
- Pass all request data (user ID, headers, form data) as task arguments — never access
requestinside a task - Use a custom
ContextTaskbase class to wrap tasks inapp.app_context()for database and config access - Celery tasks can use
current_app(with app context) but neverrequestorsession - Serialize only primitive types as task arguments — re-query models inside the task
- Use the Flask factory pattern with
celery.Task = ContextTaskfor production applications
Related reading
- Write a custom Kafka connect single message transform
- Write parquet from AWS Kinesis firehose to AWS S3
- Write to two Kafka topics in a single transaction using Spring Kafka
- Writing Custom Kafka Serializer
- Working with UTF-8 encoding in Python source
- worst-case time complexity of str.find in python
- WPF global exception handler
- Wrong count with cassandra-cql

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.