Application & Request Context (g, current_app)
A Flask context is the temporary state Flask sets up around each request so globals like current_app , g , and request point to the right things.
Learn Application & Request Context (g, current_app) in our free Flask course — a beginner-friendly interactive lesson with worked examples, a practice…
Part of the free Flask course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
In this lesson you'll learn how the application context and request context differ, how to stash per-request data on g , how to reach the active app through current_app , why the "Working outside of application context" error appears, and the two ways to fix it.
Flask gives you a handful of "magic" globals — current_app , g , request , and session — that always seem to point at the right thing. They work because Flask wraps each request in two layers of state. The application context binds current_app and g to the app that is handling the work, and the request context binds request and session to the specific HTTP request being served.
The application context lives for the length of a request or any block you open with app.app_context() . The request context lives for exactly one HTTP request. During a normal request Flask pushes the application context first, then the request context on top, so both are available everywhere in your view code.
The catch: these proxies are useless when there is no context active — for example at import time, inside a plain script, or in a background thread. Touch current_app in that situation and Flask raises a clear RuntimeError : Working outside of application context . Pushing a context with app.app_context() fixes it.
The first access fails because nothing has pushed a context yet; the second succeeds because with app.app_context(): makes current_app point at your app for the duration of the block.
g (short for "globals") is a per-request scratchpad. It is a place to compute something once — the logged-in user, a database connection, a request id — and read it back anywhere else in the same request without threading the value through every function call.
A common pattern is to populate g in a before_request hook so it is ready before any view runs. The view, its helpers, and even template context functions can then read g.user . Because current_app and request live in the same contexts, you can mix all three freely inside a request.
Remember the lifetime: g is wiped clean at the start of every request. It is perfect for "data for this request" and wrong for "data that should survive between requests."
The view never received user as an argument — it pulled it off g , which the before_request hook filled in moments earlier, all within the same request context.
Sometimes you need request or session outside of a live server — in a unit test, a REPL, or a helper you want to exercise in isolation. app.test_request_context(path) pushes both an application context and a request context for the URL you give it, so request , g , current_app , and session all work.
Inside the block, request.path and request.args reflect the URL you passed. You can also use g.get("key", default) to read an attribute that may not be set yet — it returns the default instead of raising AttributeError , which is handy when you are not sure a hook has run.
No server, no test client — test_request_context() alone is enough to make the request proxies behave, which is why it is so useful in tests and scripts.
Rule of thumb: need only current_app and g → app context. Also need request or session → request context.
Complete the code so a before_request hook stashes a request id on g and the view reads it back alongside the app's name. Replace each ___ .
You touched current_app or g with no context active — usually at import time, in a script, or in a background thread. Wrap the code in with app.app_context(): (or with app.test_request_context(): if you also need request ).
❌ Using g to store data across different requests
g resets at the start of every request, so values you set in one request are gone in the next. For data that must persist, use a database, a cache, or a signed session — not g .
Reach current_app.config outside of any request and cache a computed value on g within the same context.
Lesson complete — the magic globals aren't magic anymore!
You understand the difference between the application context ( current_app , g ) and the request context ( request , session ), why "Working outside of application context" happens, and how app.app_context() and app.test_request_context() fix it.
🚀 Up next: Request Hooks — run code before and after every request with before_request and after_request.
Practice quiz
What does the application context bind?
- request and session
- current_app and g
- url_for and redirect
- jsonify and abort
Answer: current_app and g. The application context binds current_app and g to the active app.
What does the request context bind?
- current_app and g
- config and extensions
- request and session
- Blueprint and url_prefix
Answer: request and session. The request context binds request and session to a specific HTTP request.
Which error appears when you touch current_app with no context active?
- Working outside of application context
- 404 Not Found
- Method Not Allowed
- Internal Server Error
Answer: Working outside of application context. Flask raises RuntimeError: Working outside of application context.
What is flask.g best used for?
- Caching data across many requests
- Per-request scratch storage shared across functions
- Storing settings permanently
- Signing session cookies
Answer: Per-request scratch storage shared across functions. g is a per-request scratchpad, reset on every request.
Which call pushes only an application context?
- app.test_request_context()
- app.test_client()
- app.run()
- app.app_context()
Answer: app.app_context(). app.app_context() pushes an application context so current_app and g work.
Which call gives you request and session outside a server?
- app.app_context()
- app.test_request_context()
- current_app.config
- g.get()
Answer: app.test_request_context(). test_request_context() pushes both an app and a request context.
When is g reset?
- At the start of every request
- Once per app startup
- When the server shuts down
- Never, it persists
Answer: At the start of every request. g is wiped clean at the start of every request.
During a normal request, which context is pushed first?
- The request context
- The session context
- The application context
- They are pushed simultaneously
Answer: The application context. Flask pushes the application context first, then the request context on top.
How do you read g safely when an attribute may not be set?
- g.user always works
- user
g.get('key', default) returns the default instead of raising AttributeError.
You only need current_app and g in a script. Which context fits?
- A request context
- The application context
- A test client
- No context needed
Answer: The application context. Need only current_app and g means the application context is enough.