App Factory & Config
Reviewed & published by Brayan K
The application factory is a function that builds and returns a configured Flask app on demand, instead of creating one global app at import time — making your project easier to test, configure, and scale.
Part of the free Flask course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.
In this lesson you'll write a create_app() factory, organize settings into configuration classes, and load secrets from environment variables.
What You'll Learn in This Lesson
- What the application factory pattern is and why it helps
- How to write a create_app() function
- Organizing settings into Config classes
- Loading config with app.config.from_object
- Reading secrets from environment variables
- Initializing extensions with init_app()
1 Why a Factory Function?
In small examples you create the app once at the top of app.py. That global app is fine for a demo, but it hard-codes one configuration and makes testing awkward because there is no clean way to build a fresh app with different settings.
The application factory solves this by moving app creation into a function. Each call to create_app() returns a brand-new, fully configured app — ideal for production, development, and tests side by side.
🧩 Benefits of the factory pattern:
- Testable: build a separate app with a test config for each test run
- Configurable: pass a different config class for dev vs production
- No circular imports: extensions are created once and attached later
- Scalable: register blueprints cleanly as your project grows
2 Configuration Classes
A config class is a plain Python class whose attributes become Flask settings. Put shared values in a base Config class, then subclass it for each environment. Read anything sensitive from an environment variable.
# config.py — settings grouped into classes
import os
class Config:
# Shared defaults for every environment.
# Read the secret from the environment; fall back only for local dev.
SECRET_KEY = os.environ.get("SECRET_KEY", "dev-only-secret")
SQLALCHEMY_TRACK_MODIFICATIONS = False
class DevelopmentConfig(Config):
DEBUG = True
SQLALCHEMY_DATABASE_URI = "sqlite:///dev.db"
class TestingConfig(Config):
TESTING = True
SQLALCHEMY_DATABASE_URI = "sqlite:///:memory:"
class ProductionConfig(Config):
DEBUG = False
# In production the database URL MUST come from the environment.
SQLALCHEMY_DATABASE_URI = os.environ.get("DATABASE_URL")
print("DevelopmentConfig DEBUG:", DevelopmentConfig.DEBUG)
print("TestingConfig DB:", TestingConfig.SQLALCHEMY_DATABASE_URI)
# ✅ Expected output:
# DevelopmentConfig DEBUG: True
# TestingConfig DB: sqlite:///:memory:3 Writing create_app()
The factory creates the app, loads a config object with app.config.from_object, attaches each extension with init_app, registers routes, and returns the finished app. Extensions are defined once at module level so they can be shared.
# __init__.py — the application factory
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
# Create extensions WITHOUT an app — they are bound inside the factory.
db = SQLAlchemy()
def create_app(config_object="config.DevelopmentConfig"):
app = Flask(__name__)
# Load all settings from the chosen config class.
app.config.from_object(config_object)
# Bind the extension to THIS app instance.
db.init_app(app)
# Register routes (a blueprint would go here in a bigger app).
@app.route("/")
def home():
return "App built by the factory!"
return app
# Running locally: flask run (Flask finds create_app automatically)
app = create_app()
print("Factory produced app:", app.name)
print("SECRET_KEY set:", bool(app.config["SECRET_KEY"]))When you run flask run, Flask looks for a create_app or make_app factory automatically. You can also choose a config by passing a different class name, like create_app("config.ProductionConfig").
🎯 Your Turn: Fill in the Blanks
Complete the factory below. Replace each ___ so it creates the app, loads the config, and binds the database.
# 🎯 YOUR TURN: replace each ___ to finish the factory
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
def create_app(config_object="config.DevelopmentConfig"):
app = ___(__name__) # create the application object
app.config.___(config_object) # load settings from the config class
db.___(app) # bind the database to this app
return app
application = create_app()
print("Built:", application.name)Common Errors & Quick Reference
❌ RuntimeError: Working outside of application context
You used db or current_app before an app existed. Inside the factory, wrap setup code in with app.app_context(): when you need it.
❌ ImportError: cannot import name 'app' (circular import)
This happens when modules import a global app. The fix is the factory pattern: create extensions without an app and bind them with init_app inside create_app().
| Task | Command / Code |
|---|---|
| Load a config class | app.config.from_object(...) |
| Read an env variable | os.environ.get("SECRET_KEY") |
| Bind an extension | db.init_app(app) |
| Run the app | flask run |
🏆 Mini Challenge: A Testing Factory
Make your factory accept a config so a test can build an app with an in-memory database.
- Add a TestingConfig with an in-memory SQLite URI
- Call create_app("config.TestingConfig")
- Confirm the app's TESTING flag is on
# 🏆 Mini Challenge: build a test app from the factory
import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class TestingConfig:
TESTING = True
SECRET_KEY = "test-secret"
SQLALCHEMY_DATABASE_URI = "sqlite:///:memory:"
def create_app(config_object):
app = Flask(__name__)
app.config.from_object(config_object)
db.init_app(app)
return app
test_app = create_app(TestingConfig)
print("TESTING mode:", test_app.config["TESTING"])
print("Using DB:", test_app.config["SQLALCHEMY_DATABASE_URI"])❓ Frequently Asked Questions
Lesson complete — your app is structured to scale!
You can now build apps with a create_app() factory, organize settings into config classes, and read secrets from the environment. This is how professional Flask projects are laid out.
Practice quiz
What is the application factory pattern?
- A global app created at import time
- A class that subclasses Flask
- A function that builds and returns a configured app
- A config file format
Answer: A function that builds and returns a configured app. create_app() builds and returns a configured Flask app on demand.
What is the conventional name for the factory function?
- create_app
- make_flask
- build
- init_app
Answer: create_app. The factory is usually named create_app().
Which method loads settings from a config class?
- app.config.from_mapping
- app.config.from_object
- app.config.load_class
- app.config.import_object
Answer: app.config.from_object. app.config.from_object(config_object) loads settings from a class.
How do you bind an extension like SQLAlchemy inside the factory?
- SQLAlchemy(app) at import
- db.bind(app)
- db.attach(app)
- db.init_app(app)
Answer: db.init_app(app). Create the extension without an app, then call db.init_app(app) inside create_app().
Why create extensions at module level without an app?
- To avoid circular imports and share them across apps
- To make them run faster
- Because Flask requires it
- To skip configuration
Answer: To avoid circular imports and share them across apps. Creating extensions without an app avoids circular imports and lets apps share them.
Where should secrets like SECRET_KEY come from?
- Hard-coded in config.py
- Environment variables via os.environ
- The HTML template
- The URL query string
Answer: Environment variables via os.environ. Read secrets from environment variables so they stay out of source code.
Why does the factory pattern make testing easier?
- It disables routes
- It removes the need for a database
- It builds a fresh app with a test config per run
- It runs tests automatically
Answer: It builds a fresh app with a test config per run. Each create_app() call builds a separate app with whatever config you pass.
What does flask run look for to start the app?
- A run.py script only
- A global variable named server
- An app.run() call
- A create_app or make_app factory automatically
Answer: A create_app or make_app factory automatically. flask run finds a create_app or make_app factory automatically.
How do you choose a different config when calling the factory?
- create_app('config.ProductionConfig')
- create_app(production=True)
- create_app().use_prod()
- set FLASK_PROD=1 only
Answer: create_app('config.ProductionConfig'). Pass the config object path, like create_app('config.ProductionConfig').
What does app.config behave like?
- A read-only tuple
- A frozen set
- A dictionary-like object
- A function
Answer: A dictionary-like object. app.config is a dictionary-like object of settings.
Continue this course
- Previous: Authentication & Login
- Next: Testing Flask Apps — Write automated tests with the Flask test client and pytest
- Quick reference: Flask cheat sheet
Frequently asked questions
What is the application factory pattern?
It is a function — usually named create_app() — that builds and returns a configured Flask app. Instead of creating the app at import time, you create it on demand, which makes testing and multiple configurations much easier.
Why use configuration classes?
Config classes let you keep development, testing, and production settings in separate, readable groups. You load whichever one you need with app.config.from_object, so the same code runs in every environment.
Where should secrets like passwords go?
Never hard-code secrets in your config file. Read them from environment variables with os.environ so they stay out of your source code and version control.
How do extensions fit into the factory pattern?
You create extensions like SQLAlchemy at module level without an app, then call ext.init_app(app) inside create_app(). This avoids circular imports and lets each app instance share the same extension objects.