Implementation:Langgenius Dify Create App
| Knowledge Sources | Dify |
|---|---|
| Domains | Backend, Architecture, Flask, Deployment |
| Last Updated | 2026-02-12 00:00 GMT |
Overview
Concrete tool for constructing a fully initialized Dify Flask application instance with all 26 extensions loaded in the correct order, provided by the create_app() factory function in api/app_factory.py.
Description
The app_factory.py module at api/app_factory.py provides two factory functions:
create_app()(line 63) -- Creates a full-featuredDifyAppinstance used by Gunicorn in the API container and by the Celery worker. Initializes all 26 extensions in sequence.create_migrations_app()(line 152) -- Creates a minimal app with onlyext_databaseandext_migrateinitialized. Used exclusively for running Flask-Migrate database migrations (e.g.,flask db upgrade).
The initialize_extensions() function (line 73) iterates through a list of extension modules. Each module must expose an init_app(app) function. Optionally, modules may provide an is_enabled() function to conditionally disable themselves.
The initialization sequence is:
extensions = [
ext_timezone,
ext_logging,
ext_warnings,
ext_import_modules,
ext_orjson,
ext_forward_refs,
ext_set_secretkey,
ext_compress,
ext_code_based_extension,
ext_database,
ext_app_metrics,
ext_migrate,
ext_redis,
ext_storage,
ext_logstore,
ext_celery,
ext_login,
ext_mail,
ext_hosting_provider,
ext_sentry,
ext_proxy_fix,
ext_blueprints,
ext_commands,
ext_fastopenapi,
ext_otel,
ext_request_logging,
ext_session_factory,
]
In the Docker deployment, the API container runs Gunicorn which calls create_app() in each worker process. The worker container invokes the same factory through Celery. The MIGRATION_ENABLED=true environment variable controls whether the API container runs database migrations at startup.
Usage
Import and call create_app() when bootstrapping the Dify API server or Celery worker. Use create_migrations_app() when running database schema migrations.
Code Reference
Source Location: api/app_factory.py, lines 63-70 (create_app), lines 73-149 (initialize_extensions), lines 152-160 (create_migrations_app)
Signature:
def create_app() -> DifyApp:
start_time = time.perf_counter()
app = create_flask_app_with_configs()
initialize_extensions(app)
end_time = time.perf_counter()
if dify_config.DEBUG:
logger.info("Finished create_app (%s ms)", round((end_time - start_time) * 1000, 2))
return app
def initialize_extensions(app: DifyApp):
# Imports 26 extension modules from extensions package
# Initializes Flask context capture for workflow execution
from context.flask_app_context import init_flask_context
init_flask_context()
extensions = [ext_timezone, ext_logging, ..., ext_session_factory]
for ext in extensions:
short_name = ext.__name__.split(".")[-1]
is_enabled = ext.is_enabled() if hasattr(ext, "is_enabled") else True
if not is_enabled:
continue
start_time = time.perf_counter()
ext.init_app(app)
# Logs timing in DEBUG mode
def create_migrations_app() -> DifyApp:
app = create_flask_app_with_configs()
ext_database.init_app(app)
ext_migrate.init_app(app)
return app
Import statement:
from app_factory import create_app, create_migrations_app
I/O Contract
Inputs
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| Environment variables | os.environ | Yes | From .env / dify_config | All configuration is read from environment variables via the dify_config Pydantic model
|
| Flask config | dict | Auto | dify_config.model_dump() | Configuration dictionary loaded into app.config
|
Outputs
| Output | Type | Description |
|---|---|---|
| DifyApp instance | DifyApp | Fully configured Flask application with all extensions initialized, ready to serve requests |
| DifyApp (migrations) | DifyApp | Minimal Flask application with only database and migration extensions, for schema management |
Usage Examples
API server startup via Gunicorn (Docker entrypoint):
# In the Gunicorn configuration or WSGI entry point:
from app_factory import create_app
app = create_app()
# Gunicorn binds to 0.0.0.0:5001 with gevent workers
Celery worker initialization:
# The Celery extension (ext_celery) patches the Flask app context
# The worker container uses MODE=worker which invokes Celery
# Celery internally calls create_app() to establish the Flask context
Database migration (using create_migrations_app):
# Used by Flask-Migrate CLI commands:
# flask db upgrade
# This creates a lightweight app with only database + migration extensions
from app_factory import create_migrations_app
app = create_migrations_app()
# Only ext_database and ext_migrate are initialized
# No Redis, Celery, or other heavy services required
Debug timing output (when DEBUG=true):
INFO: Loaded ext_timezone (0.12 ms)
INFO: Loaded ext_logging (1.45 ms)
INFO: Loaded ext_database (23.67 ms)
INFO: Loaded ext_redis (5.34 ms)
INFO: Loaded ext_celery (45.89 ms)
...
INFO: Finished create_app (312.45 ms)