This document covers the deployment architecture, service orchestration, configuration management, and operational aspects of running Dify in production environments. The platform is designed for containerized deployment using Docker and Docker Compose, with support for various infrastructure backends and scaling options.
For information about the overall system architecture and service topology, see System Architecture Overview. For details on the Docker build process and multi-stage image construction, see Docker Build Process and Multi-Stage Images. For comprehensive environment configuration details, see Environment Configuration and Runtime Modes.
Dify follows a microservices architecture orchestrated through Docker Compose, with clear separation between application services, data persistence, and external integrations.
Sources: docker/docker-compose-template.yaml1-132 docker/docker-compose.yaml1-100
The platform uses health checks and dependency management to ensure services start in the correct order:
Sources: docker/docker-compose-template.yaml39-94 docker/docker-compose.yaml39-128
The init_permissions container ensures storage directories have correct ownership (1001:1001) before application services start. Database services use health checks (pg_isready for PostgreSQL, mysqladmin ping for MySQL) with 30-60 retries at 1-second intervals.
The API image (langgenius/dify-api) runs in different modes controlled by the MODE environment variable:
| Mode | Service | Purpose | Entry Point |
|---|---|---|---|
api | api | HTTP API server (Flask + Gunicorn) | Serves REST API on port 5001 |
worker | worker | Celery worker for background tasks | Processes queues: dataset, workflow, mail |
beat | worker_beat | Celery beat scheduler | Triggers periodic tasks |
Sources: docker/docker-compose-template.yaml22-131 docker/entrypoint.sh1-80
All API-based services (api, worker, worker_beat) share a common environment configuration using YAML anchors:
This ensures consistent configuration across all backend services. The configuration spans database settings, storage backends, vector databases, LLM providers, security keys, and operational parameters.
Sources: docker/docker-compose.yaml7-650 docker/.env.example1-800
PostgreSQL is the default database, configured with performance tuning parameters:
Key parameters:
max_connections: Maximum concurrent connections (default 100)shared_buffers: Shared memory for caching (default 128MB, recommended 25% of available RAM)work_mem: Memory per query operation (default 4MB)effective_cache_size: Planner's cache size assumption (default 4GB)statement_timeout: Max statement execution time (0 = unlimited)Sources: docker/docker-compose-template.yaml163-180 docker/.env.example265-307
MySQL can be used as an alternative to PostgreSQL:
Key InnoDB parameters:
innodb_buffer_pool_size: Memory pool for caching (default 512M, recommended 70-80% of RAM)innodb_log_file_size: Transaction log size (default 128M)innodb_flush_log_at_trx_commit: Flush behavior (2 = flush to OS cache, sync every second)Sources: docker/docker-compose-template.yaml200-227 docker/.env.example309-330
The application configures SQLAlchemy connection pooling:
Total maximum connections = POOL_SIZE + MAX_OVERFLOW = 40 by default. Ensure database max_connections exceeds this.
Sources: docker/.env.example248-263 api/configs/middleware/__init__.py80-120
Redis serves three critical functions: caching, pub/sub for real-time updates, and Celery message broker.
Different Redis databases are used for different purposes:
| Database | Purpose | Configuration Variable |
|---|---|---|
0 | Application cache and pub/sub | REDIS_DB=0 |
1 | Celery broker | CELERY_BROKER_URL=redis://:password@redis:6379/1 |
Sources: docker/docker-compose-template.yaml229-245 docker/.env.example332-391
For high availability, Redis Sentinel mode is supported:
The application automatically discovers and connects to the master node through Sentinel.
Sources: docker/.env.example353-389 api/configs/middleware/cache/redis_config.py1-100
Redis Cluster mode is also supported for horizontal scaling:
Sources: docker/.env.example365-369
Sources: docker/docker-compose-template.yaml64-131 api/app.py1-38
Workers can be scaled statically or with autoscaling:
The CELERY_AUTO_SCALE flag enables dynamic worker adjustment based on queue depth. Autoscaling is useful for CPU-intensive tasks that can be parallelized.
Sources: docker/.env.example189-215
The gevent worker class provides better concurrency for I/O-bound tasks. Changing this requires modifying gunicorn.conf.py and celery_entrypoint.py to disable monkey patching.
Sources: docker/.env.example175-183
Dify supports multiple storage backends for user files, documents, and generated content.
Sources: docker/.env.example414-534 api/configs/middleware/storage/opendal_storage_config.py1-50
OpenDAL provides a unified interface for multiple storage backends:
OpenDAL configuration follows the pattern OPENDAL_<SCHEME_NAME>_<CONFIG_NAME>. Dify automatically scans and applies all environment variables matching this pattern.
Sources: docker/.env.example416-425 extensions/storage/opendal_storage.py1-100
Direct S3 configuration (without OpenDAL):
When S3_USE_AWS_MANAGED_IAM=true, IAM roles are used instead of access keys (for EC2/ECS deployments).
Sources: docker/.env.example446-455
Local storage requires volume mounts with correct permissions:
All services running with user ID 1001 can access this shared storage.
Sources: docker/docker-compose-template.yaml4-20 docker/docker-compose-template.yaml56-59
Dify supports 30+ vector database backends for semantic search and RAG applications.
Supported values: weaviate, qdrant, milvus, pgvector, pgvecto-rs, chroma, opensearch, elasticsearch, oceanbase, seekdb, myscale, relyt, analyticdb, couchbase, tidb, tidb_on_qdrant, oracle, tencent, baidu, lindorm, vikingdb, upstash, matrixone, opengauss, vastbase, tablestore, clickzetta, alibabacloud_mysql, iris, huawei_cloud.
Sources: docker/.env.example540-542 core/rag/datasource/vdb/vector_type.py1-50
Application configuration:
Sources: docker/.env.example546-550 docker/docker-compose.middleware.yaml200-250
Sources: docker/.env.example569-575
Uses PostgreSQL with pgvector extension:
Sources: docker/.env.example605-614
The Vector class in core/rag/datasource/vdb/vector_factory.py38-100 implements a factory pattern for vector database initialization:
This abstracts vector database operations behind a common interface.
Sources: core/rag/datasource/vdb/vector_factory.py27-100
The sandbox provides isolated code execution for workflow code nodes and tool operations.
Network access is proxied through the SSRF proxy for security.
Sources: docker/docker-compose-template.yaml247-270
API services connect to the sandbox:
Sources: docker/.env.example461-468 api/configs/feature/__init__.py103-146
Safety limits for code execution:
Sources: docker/.env.example444-451 api/configs/feature/__init__.py148-186
The SSRF (Server-Side Request Forgery) proxy protects against unauthorized external requests.
Sources: docker/docker-compose.middleware.yaml300-350
Sources: docker/.env.example443-453 docker/.env.example566-576
The plugin daemon runs user-installed plugins in isolated environments.
The plugin daemon uses a separate database (dify_plugin) to isolate plugin data from application data.
Sources: docker/docker-compose-template.yaml271-320
Plugins can store data in various backends:
Plugin paths:
PLUGIN_INSTALLED_PATH=plugin - Installed plugin codePLUGIN_PACKAGE_CACHE_PATH=plugin_packages - Downloaded packagesPLUGIN_MEDIA_CACHE_PATH=assets - Generated media filesSources: docker/.env.example614-642 docker/docker-compose-template.yaml294-316
Bidirectional communication between API and plugin daemon:
The inner API key authenticates plugin callbacks to the main API.
Sources: docker/.env.example590-603 api/configs/feature/__init__.py221-241
Nginx serves as the entry point, handling SSL termination and routing.
Sources: docker/nginx/conf.d/default.conf1-100
Long proxy timeouts support streaming responses and long-running workflows.
Sources: docker/.env.example550-562
Certbot integration for automatic SSL certificates:
Certbot uses the ACME protocol to obtain certificates from Let's Encrypt.
Sources: docker/.env.example562-565
JSON format is recommended for production to enable structured log analysis.
Sources: docker/.env.example72-86
When enabled, logs all HTTP requests and responses at DEBUG level. Use cautiously in production due to performance impact.
Sources: docker/.env.example97-99
Error tracking with Sentry:
Sources: docker/.env.example409-415
The SECRET_KEY is critical for security. Change it before deployment and keep it secret.
Sources: docker/.env.example101-104 api/configs/feature/__init__.py20-30
Sets the password for the initial admin account. Leave empty to prompt during setup.
Sources: docker/.env.example106-110
Sources: docker/.env.example135-139 api/configs/feature/__init__.py32-50
For production, specify allowed origins instead of using *.
Sources: docker/.env.example397-409
Health checks ensure services are ready before accepting traffic.
Sources: docker/docker-compose.middleware.yaml27-41 docker/docker-compose.middleware.yaml119-120
When enabled, exports traces and metrics to OpenTelemetry collectors.
Sources: docker/.env.example643-648
Generate Secure Keys
Configure Database
POSTGRES_MAX_CONNECTIONS based on expected loadshared_buffers to 25% of available RAMConfigure Storage
Configure Vector Database
Configure Redis
Sources: Multiple files referenced throughout sections
For load balancing multiple API instances, use an external load balancer or Docker Swarm/Kubernetes.
| Service | Parameter | Default | Recommendation |
|---|---|---|---|
| Gunicorn | SERVER_WORKER_AMOUNT | 1 | CPU cores × 2 + 1 |
| Gunicorn | GUNICORN_TIMEOUT | 360 | 600 for long workflows |
| Celery | CELERY_WORKER_AMOUNT | 1 | 4-8 per instance |
| Database | POSTGRES_SHARED_BUFFERS | 128MB | 25% of RAM |
| Database | SQLALCHEMY_POOL_SIZE | 30 | Based on connections |
Sources: docker/.env.example159-215
| Variable | Default | Description |
|---|---|---|
DB_TYPE | postgresql | Database type: postgresql, mysql, oceanbase, seekdb |
DB_HOST | db_postgres | Database host |
REDIS_HOST | redis | Redis host |
REDIS_PASSWORD | difyai123456 | Redis password |
CELERY_BROKER_URL | redis://:pass@redis:6379/1 | Celery message broker |
STORAGE_TYPE | opendal | Storage backend type |
VECTOR_STORE | weaviate | Vector database type |
CODE_EXECUTION_ENDPOINT | http://sandbox:8194 | Sandbox URL |
PLUGIN_DAEMON_URL | http://plugin_daemon:5002 | Plugin daemon URL |
Sources: docker/.env.example1-800 docker/docker-compose.yaml1-650
These URLs control how the frontend communicates with backend services and how external systems access the platform.
Sources: docker/.env.example8-58
Sources: docker/.env.example88-116
Profiles control which database service starts.
Sources: docker/docker-compose-template.yaml165-167 docker/docker-compose.middleware.yaml1-350
Permission Errors
Database Connection Failures
Redis Connection Issues
Vector Database Connection
When troubleshooting, restart services in this order:
Sources: Based on dependency graph in docker/docker-compose-template.yaml39-131
Refresh this wiki