Jesse A. Green / notebook

Dify — User Guide

Generated May 2026 from langgenius/dify at 13a9359

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

Dify is an open-source platform for building LLM-powered applications. It provides a visual workflow editor, RAG (Retrieval-Augmented Generation) pipeline, agent framework, model management, and observability — all through a browser-based interface. You can build chatbots, text generators, workflow automations, and AI agents without writing code, then expose them via API or embeddable web apps.

Tip

New to Dify? Jump to Quick Start for a 5-minute Docker setup, or Installation for production deployments. The Building Applications section walks through creating each app type.


Table of Contents


Quick Start

Get Dify running locally in under 5 minutes with Docker Compose.

Prerequisites

  • Docker Engine >= 19.03 and Docker Compose >= 2.x
  • At least 4 GB RAM (8 GB recommended)
  • x86_64 or ARM64 CPU

Steps

# Clone the repository
git clone https://github.com/langgenius/dify.git
cd dify/docker

# Copy the example environment file
cp .env.example .env

# Start all services
docker compose up -d

Once containers are healthy (check with docker compose ps), open http://localhost in your browser. You will see the initial setup screen.

First-Time Setup

  1. Navigate to http://localhost/install
  2. Create your admin account (email + password)
  3. Set up your first workspace
  4. Add at least one LLM provider (e.g., OpenAI, Anthropic, or a local Ollama instance)

Important

The INIT_PASSWORD environment variable, if set, is required during the /install step. This provides an extra layer of protection for the initial setup endpoint.

After setup, the /install endpoint is permanently disabled for that deployment.


Installation

The docker/ directory contains a production-ready docker-compose.yaml that orchestrates all required services:

Container Role Default Port
nginx Reverse proxy, static files 80, 443
web Next.js frontend 3000 (internal)
api Flask API server 5001 (internal)
worker Celery background worker --
db PostgreSQL database 5432 (internal)
redis Cache, queue broker, sessions 6379 (internal)
weaviate Default vector store 8080 (internal)
plugin_daemon Go-based plugin runtime 5002 (internal)
sandbox Secure code execution 8194 (internal)
ssrf_proxy Outbound request proxy 3128 (internal)
certbot SSL certificate automation --
cd dify/docker
cp .env.example .env
# Edit .env to configure your deployment (see Configuration below)
docker compose up -d

Environment Sync Tool

When upgrading Dify, new environment variables may be added to .env.example. Use the built-in sync tool to merge them:

python docker/dify-env-sync.py
# Options:
#   --dir <path>    Working directory (default: current)
#   --no-backup     Skip timestamped .env backup

This preserves your existing values while adding new variables with their defaults.

Source Installation

For development or customization:

Backend (API)

cd api
# Install uv (Python package manager)
pip install uv
# Create virtual environment and install dependencies
uv sync --all-extras
# Copy environment configuration
cp .env.example .env
# Initialize database
uv run flask upgrade-db
# Start the API server
uv run gunicorn --bind 0.0.0.0:5001 --worker-class gevent app:app

Backend (Worker)

cd api
uv run celery -A app.celery worker -Q dataset,generation,mail,ops_trace --loglevel INFO

Frontend

cd web
# Requires Node.js 22.22.1+ and pnpm 10.33.0+
pnpm install
pnpm dev
# Production build:
pnpm build && pnpm start

Note

The frontend uses pnpm exclusively -- npm and yarn are not supported. The preinstall script enforces this with only-allow pnpm.

System Requirements

Component Minimum Recommended
CPU 2 cores 4+ cores
RAM 4 GB 8+ GB
Disk 20 GB 50+ GB (grows with knowledge base)
Docker 19.03+ Latest stable
Docker Compose 2.x Latest stable
Node.js 22.22.1 22.22.1
Python 3.12+ 3.12+
PostgreSQL 15+ 16+
Redis 6+ 7+

Upgrading

cd dify/docker
git pull origin main
docker compose down
docker compose pull
# Sync any new environment variables
python dify-env-sync.py
docker compose up -d

Database migrations run automatically on API container startup via flask upgrade-db.


Core Concepts

Application Types

Dify supports five distinct application types, each suited to different use cases:

Type Description Use Case
Chat Multi-turn conversational interface Customer support, FAQ bots
Completion Single prompt to single response Content generation, summarization
Workflow Visual DAG-based automation Data processing, multi-step reasoning
Agent-Chat Chat with autonomous tool use Research assistants, data analysts
Advanced-Chat Chat backed by a workflow Complex conversational flows with branching logic

Workspaces and Tenants

A workspace (internally called a "tenant") is the top-level organizational unit. Each workspace has:

  • Its own set of applications, datasets, and model configurations
  • Member management with role-based access (Owner, Admin, Editor, Viewer, Dataset Operator)
  • Separate API key scoping
  • Independent usage quotas

Models and Providers

Dify acts as a model abstraction layer. You configure model providers (OpenAI, Anthropic, Azure OpenAI, Google, local Ollama/vLLM, etc.) in Settings, then select specific models per application. This means:

  • Swap models without changing application logic
  • Use different models for different tasks (cheap model for classification, powerful model for generation)
  • Self-hosted models work the same as cloud APIs

Datasets (Knowledge Base)

A dataset is a collection of documents processed for retrieval. Documents go through:

  1. Upload -- files (PDF, DOCX, TXT, Markdown, HTML, CSV, Excel, EPUB) or web crawl
  2. Processing -- extraction, cleaning, chunking
  3. Embedding -- vector embeddings stored in the configured vector database
  4. Indexing -- full-text and/or semantic search indexes

Datasets can be shared across multiple applications.

Plugins

Plugins extend Dify's capabilities. They run in a separate Go-based daemon (plugin_daemon) and communicate via JSON-RPC. Plugin types include:

  • Model providers -- add new LLM/embedding/reranker backends
  • Tools -- give agents and workflows callable actions
  • Extensions -- custom endpoints, triggers, data sources

Plugins are distributed as .difypkg files and can be installed from the Marketplace or uploaded manually.


Building Applications

Creating an App

  1. From the dashboard, click Create App
  2. Choose your application type (Chat, Completion, Workflow, Agent-Chat, or Advanced-Chat)
  3. Name your app and optionally provide a description and icon

Configuring a Chat App

  1. Model -- Select the LLM and adjust parameters (temperature, top-p, max tokens, etc.)
  2. System Prompt -- Define the persona, instructions, and constraints
  3. Context -- Attach datasets for RAG-powered responses
  4. Features -- Enable/disable:
    • Citation and attribution
    • Content moderation (OpenAI moderation, custom keywords, or API-based)
    • Speech-to-text / Text-to-speech
    • Suggested follow-up questions
    • Opening statement / Suggested openers

Configuring a Completion App

  1. Model -- Same model selection as Chat
  2. Prompt Template -- Write a prompt with {{variable}} placeholders
  3. Variables -- Define input variables that users fill in (text, paragraph, select, number)
  4. Context -- Optional RAG attachment

Variables

Variables let you create dynamic, reusable prompts:

Type Description
text-input Short single-line text
paragraph Multi-line text area
select Dropdown with predefined options
number Numeric input
file File upload (images, documents)
file-list Multiple file uploads

Reference variables in prompts with {{variable_name}} syntax.

Orchestration Modes

  • Simple -- Direct prompt, model, and response (suitable for most chat/completion apps)
  • Workflow -- Visual DAG editor for complex logic (see Workflows)

Publishing and Versioning

Once configured, you can:

  • Run/Preview -- Test in the built-in playground
  • Publish -- Make the app available via API and web app
  • Version History -- DSL-based export/import for application configurations

Tip

Export your app configuration as YAML DSL for version control, backup, or sharing. Use Export DSL from the app settings to download the configuration file.


Models

Adding Model Providers

Navigate to Settings and configure:

  1. Cloud APIs -- Enter API keys for OpenAI, Anthropic, Google, Azure OpenAI, Cohere, Minimax, Zhipu, Baichuan, and others
  2. Self-hosted Models -- Point to Ollama, vLLM, Xinference, LocalAI, or any OpenAI-compatible endpoint
  3. Custom Models -- Add custom model definitions with specific parameters

Model Types

Type Purpose Example
LLM Text generation GPT-4o, Claude Sonnet
Text Embedding Vector embeddings for RAG text-embedding-3-large
Reranker Re-rank search results bge-reranker-v2-m3
Speech-to-Text Audio transcription Whisper
Text-to-Speech Voice synthesis TTS-1
Moderation Content filtering text-moderation-latest

Model Parameters

When selecting a model in an app, you can tune:

  • Temperature -- Randomness (0 = deterministic, 1 = creative)
  • Top P -- Nucleus sampling threshold
  • Max Tokens -- Response length limit
  • Presence Penalty -- Penalize repeated topics
  • Frequency Penalty -- Penalize repeated tokens
  • Stop Sequences -- Tokens that terminate generation

Default Models

Set system-wide defaults in Settings under System Model Settings:

  • Default LLM for inference
  • Default embedding model for datasets
  • Default reranker for search
  • Default speech-to-text / text-to-speech models

Knowledge Base (RAG)

Creating a Dataset

  1. Go to Knowledge in the sidebar

  2. Click Create Knowledge and choose a data source:

    • Upload files -- PDF, DOCX, TXT, MD, HTML, CSV, XLSX, EPUB
    • Sync from Notion -- Connect Notion workspace pages
    • Sync from website -- Crawl via Firecrawl, Jina Reader, or WaterCrawl
  3. Configure processing settings:

    • Chunking strategy -- Automatic, custom (separator + chunk size), or parent-child
    • Chunk size -- Token count per segment (default: 500, max configurable via INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH, default 4000)
    • Chunk overlap -- Overlapping tokens between segments
    • Cleaning rules -- Remove extra whitespace, URLs, emails
  4. Choose indexing mode:

    • High Quality -- Embedding + vector search (requires embedding model)
    • Economical -- Keyword-based full-text search (no embedding needed)

Retrieval Modes

When attaching a dataset to an app, choose the retrieval strategy:

Mode How It Works Best For
Semantic Search Vector similarity (cosine/L2) Natural language queries
Full-Text Search Keyword/BM25 matching Exact term lookups
Hybrid Search Both semantic + full-text, merged Best overall recall

Parameters:

  • Top K -- Number of chunks to retrieve (configurable max via NEXT_PUBLIC_TOP_K_MAX_VALUE)
  • Score Threshold -- Minimum relevance score (0-1)
  • Reranker -- Optional re-ranking model for improved precision

Multi-Dataset Retrieval

Apps can query multiple datasets simultaneously. The N-Choose-Top strategy retrieves from all datasets in parallel and merges results by relevance score.

Maintaining Datasets

  • Add documents -- Upload additional files or sync new pages
  • Re-process -- Re-chunk and re-embed existing documents with new settings
  • Disable/Enable segments -- Toggle individual chunks without deleting
  • Metadata -- View and manage document metadata
  • Hit Testing -- Test retrieval with sample queries to tune settings

Important

Re-processing a large dataset triggers re-embedding of all chunks, which consumes embedding model quota. Check your provider's rate limits before bulk re-processing.


Tools and Plugins

Built-in Tools

Dify ships with built-in tool integrations including:

  • Web Search -- Google, Bing, DuckDuckGo, SearXNG, Serper
  • Web Browsing -- Fetch and parse web pages
  • Math -- Calculator, Wolfram Alpha
  • Code -- Sandboxed Python/JavaScript execution
  • Image -- DALL-E, Stable Diffusion
  • Data -- Wikipedia, arXiv, PubMed

Custom Tools

Create tools using OpenAPI/Swagger specifications:

  1. Go to Tools and click Create Custom Tool
  2. Paste your OpenAPI 3.0 schema (JSON or YAML)
  3. Configure authentication (None, API Key, or OAuth 2.0)
  4. Test the tool endpoints

Plugin Marketplace

Browse and install community plugins from the built-in Marketplace:

  1. Go to Plugins in the sidebar
  2. Browse or search the marketplace
  3. Click Install to add a plugin

Note

The marketplace is enabled by default (MARKETPLACE_ENABLED=true). It connects to https://marketplace.dify.ai. Set MARKETPLACE_ENABLED=false in your .env to disable it for air-gapped deployments.

Plugin Configuration

  • Model Provider plugins -- Appear in Settings after installation
  • Tool plugins -- Appear in the Tools panel within apps
  • Extension plugins -- May add custom endpoints or webhooks

Plugins run in the plugin_daemon container, isolated from the main API. Communication is via JSON-RPC over stdio.

Tool and Provider Visibility

Control which tools and providers appear in the UI:

Variable Purpose
POSITION_TOOL_PINS Pin specific tools to top of list
POSITION_TOOL_INCLUDES Whitelist -- only show these tools
POSITION_TOOL_EXCLUDES Blacklist -- hide these tools
POSITION_PROVIDER_PINS Pin specific providers to top
POSITION_PROVIDER_INCLUDES Whitelist providers
POSITION_PROVIDER_EXCLUDES Blacklist providers

Endpoint-Based Extensions

Create custom HTTP endpoints served by plugins:

ENDPOINT_URL_TEMPLATE=http://localhost:5002/e/{hook_id}

Each endpoint gets a unique hook_id and can be configured with custom authentication.


Workflows

Overview

The Workflow editor is a visual, drag-and-drop DAG (Directed Acyclic Graph) builder. Each node performs an action, and edges define execution order. Workflows support parallel branches, conditional routing, loops, and human-in-the-loop approvals.

Node Types

Node Description
Start Entry point -- defines input variables
End Terminal node -- defines output variables
LLM Call a language model with a prompt template
Knowledge Retrieval Query datasets for RAG
Question Classifier Route based on intent classification
IF/ELSE Conditional branching
Code Execute Python or JavaScript in sandbox
Template Jinja2 template rendering
Variable Aggregator Merge variables from parallel branches
Variable Assigner Set or transform variables
Iteration Loop over a list, processing each item
Parameter Extractor Extract structured data from LLM output
HTTP Request Call external APIs
Tool Invoke a configured tool
Sub-Workflow Call another workflow
Assigner Direct variable assignment
Document Extractor Extract text from uploaded files
List Filter Filter arrays by condition

Execution Limits

Parameter Default Env Variable
Max steps per run 500 WORKFLOW_MAX_EXECUTION_STEPS
Max execution time 1200s (20 min) WORKFLOW_MAX_EXECUTION_TIME
Max call depth (sub-workflows) 5 WORKFLOW_CALL_MAX_DEPTH
Max variable size 200 KB MAX_VARIABLE_SIZE
Max parallel submit count 100 MAX_SUBMIT_COUNT
Max loop iterations Configurable NEXT_PUBLIC_LOOP_NODE_MAX_COUNT

Triggers

Workflows can be started by:

  • Manual -- Run from the UI or via API
  • Webhook -- Incoming HTTP requests trigger execution (WEBHOOK_REQUEST_BODY_MAX_SIZE default 10 MB)
  • Schedule (Cron) -- Time-based triggers
  • Plugin Trigger -- Events from installed plugins

Debugging Workflows

  • Single Node Run -- Test individual nodes in isolation (preview/draft mode)
  • Full Run -- Execute the entire workflow with test inputs
  • Run History -- View past executions with input/output for each node
  • Tracing -- Track execution path through parallel branches

Tip

Use the Single Node Run feature to debug complex LLM prompts or code nodes before wiring them into the full workflow.


Agents

Agent-Chat Apps

Agent-Chat apps give the LLM autonomous tool-calling ability. The agent decides when and how to use tools based on the conversation context.

Configuration

  1. Create an Agent-Chat app
  2. Select a model that supports function calling
  3. Add tools from:
    • Built-in tools
    • Custom tools (OpenAPI)
    • Plugin tools
  4. Configure agent settings:
    • Max iterations -- Limit tool-calling loops (configurable via NEXT_PUBLIC_MAX_ITERATIONS_NUM)
    • Max tools per turn -- Limit concurrent tool usage (configurable via NEXT_PUBLIC_MAX_TOOLS_NUM)

Advanced-Chat Apps

Advanced-Chat combines the conversational interface of Chat with the power of Workflows:

  1. Create an Advanced-Chat app
  2. Build a workflow that processes the user's message
  3. The workflow can include RAG retrieval, tool calls, conditional logic, and multi-step reasoning
  4. The final output node feeds back into the chat interface

This is the most flexible app type -- use it when simple prompt engineering is not sufficient but you want a conversational UX.


Web Apps and Embedding

Built-in Web App

Every published app automatically gets a shareable web app:

  1. Go to your app and open the Monitoring section or click the globe icon
  2. Share the URL with users
  3. Optionally customize:
    • App title and description
    • Welcome message / conversation openers
    • Color theme
    • Custom domain (via NEXT_PUBLIC_WEB_PREFIX)

Embedding in Your Website

Embed Dify apps into existing websites using:

iframe

<iframe
  src="https://your-dify-instance.com/chatbot/APP_TOKEN"
  width="100%"
  height="600"
  frameborder="0">
</iframe>

Script Tag

<script
  src="https://your-dify-instance.com/embed.min.js"
  id="APP_TOKEN"
  defer>
</script>

Note

Embedding requires NEXT_PUBLIC_ALLOW_EMBED=true in your frontend environment. For inline styles, also set NEXT_PUBLIC_ALLOW_INLINE_STYLES=true.


Using the APIs

Dify exposes two primary API surfaces for programmatic access.

Service API (for your back-end)

Base URL: https://your-dify-instance.com/v1

Authenticate with your app's API Key via the Authorization: Bearer {api_key} header.

Chat / Agent-Chat Endpoints

# Send a message (streaming)
curl -X POST https://your-dify-instance.com/v1/chat-messages \
  -H "Authorization: Bearer {api_key}" \
  -H "Content-Type: application/json" \
  -d '{
    "inputs": {},
    "query": "What is Dify?",
    "response_mode": "streaming",
    "user": "user-123"
  }'

# Get conversation history
curl https://your-dify-instance.com/v1/messages?conversation_id={conv_id}&user=user-123 \
  -H "Authorization: Bearer {api_key}"

# List conversations
curl https://your-dify-instance.com/v1/conversations?user=user-123 \
  -H "Authorization: Bearer {api_key}"

Completion Endpoints

curl -X POST https://your-dify-instance.com/v1/completion-messages \
  -H "Authorization: Bearer {api_key}" \
  -H "Content-Type: application/json" \
  -d '{
    "inputs": {"topic": "quantum computing"},
    "response_mode": "blocking",
    "user": "user-123"
  }'

Workflow Endpoints

# Run a workflow
curl -X POST https://your-dify-instance.com/v1/workflows/run \
  -H "Authorization: Bearer {api_key}" \
  -H "Content-Type: application/json" \
  -d '{
    "inputs": {"data": "process this"},
    "response_mode": "streaming",
    "user": "user-123"
  }'

# Get workflow run status
curl https://your-dify-instance.com/v1/workflows/run/{workflow_run_id} \
  -H "Authorization: Bearer {api_key}"

File Upload

curl -X POST https://your-dify-instance.com/v1/files/upload \
  -H "Authorization: Bearer {api_key}" \
  -F "file=@document.pdf" \
  -F "user=user-123"

Upload limits (configurable):

Parameter Default Env Variable
File size 15 MB UPLOAD_FILE_SIZE_LIMIT
Batch count 5 UPLOAD_FILE_BATCH_LIMIT
Image size 10 MB UPLOAD_IMAGE_FILE_SIZE_LIMIT
Video size 100 MB UPLOAD_VIDEO_FILE_SIZE_LIMIT
Audio size 50 MB UPLOAD_AUDIO_FILE_SIZE_LIMIT

Annotations

Annotations let you define exact input-to-output pairs that override model responses:

# Create an annotation
curl -X POST https://your-dify-instance.com/v1/apps/annotations \
  -H "Authorization: Bearer {api_key}" \
  -H "Content-Type: application/json" \
  -d '{
    "question": "What is your return policy?",
    "answer": "We offer 30-day returns on all items."
  }'

Response Modes

Mode Behavior
blocking Wait for complete response, return as JSON
streaming Server-Sent Events (SSE), tokens delivered as generated

SSE streaming events include: message, agent_message, agent_thought, message_file, message_end, tts_message, tts_message_end, error, ping, workflow_started, node_started, node_finished, workflow_finished.

Console API (for the web UI)

Base URL: https://your-dify-instance.com/console/api

Used by the Dify web interface. Authenticated via session tokens (JWT). Not intended for external integration -- use the Service API instead.

Warning

The Console API is an internal interface. Its endpoints may change between versions without notice. Use the Service API (/v1/*) for all integrations.


SDKs

Node.js SDK

npm install dify-client
import { DifyClient, ChatClient, CompletionClient } from 'dify-client';

// Initialize
const chatClient = new ChatClient(
  'your-api-key',
  'https://your-dify-instance.com/v1'
);

// Send a chat message (streaming)
const response = await chatClient.createChatMessage(
  {},          // inputs
  'Hello!',    // query
  'user-123',  // user
  true,        // streaming
  null         // conversation_id (null for new)
);

// Send a completion message
const completionClient = new CompletionClient('your-api-key');
const result = await completionClient.createCompletionMessage(
  { topic: 'AI' },  // inputs
  'user-123',        // user
  false              // streaming
);

// Run a workflow
const difyClient = new DifyClient('your-api-key');
const workflowResult = await difyClient.runWorkflow(
  { data: 'process this' },  // inputs
  'user-123',                 // user
  true                        // streaming
);

Requires Node.js >= 18.0.0. Published as dify-client v3.1.0 on npm.

PHP SDK

require 'vendor/autoload.php';

// Chat
$client = new DifyClient('your-api-key');
$chatClient = new ChatClient($client);
$response = $chatClient->chat(
    ['query' => 'Hello!', 'user' => 'user-123']
);

// Completion
$completionClient = new CompletionClient($client);
$response = $completionClient->create(
    ['inputs' => ['topic' => 'AI'], 'user' => 'user-123']
);

Requires PHP >= 7.2, Guzzle >= 7.9. Install via Composer.

Python SDK

A separate Python SDK repository is maintained at github.com/langgenius/dify-sdk-python. Refer to that repository for installation and usage.


Common Tasks

Import/Export App Configurations

Export:

App Settings -> Export DSL -> Save the YAML file

Import:

Dashboard -> Import DSL -> Select YAML file

DSL files capture the complete app configuration including prompts, model settings, tool bindings, and workflow definitions.

Duplicate an App

From the dashboard, click the menu icon on any app and select Duplicate. This creates an independent copy with all settings.

Add Conversation Openers

In your Chat or Agent-Chat app:

  1. Go to Features and find Opening Statement
  2. Write a welcome message
  3. Optionally add suggested opener buttons (pre-filled questions users can click)

Enable Citation

In Chat/Agent-Chat apps with RAG:

  1. Go to Features and find Citation and Attribution
  2. Toggle on -- responses will include source references from retrieved chunks

Content Moderation

Three moderation approaches:

  1. OpenAI Moderation -- Uses OpenAI's moderation API to filter harmful content
  2. Custom Keywords -- Define blocked words/phrases; matches trigger a preset response
  3. External API -- Call your own moderation endpoint for custom logic

Data Source Integrations

Connect external data via:

  • Notion -- Sync pages as knowledge base documents
    • Configure NOTION_INTEGRATION_TYPE (public or internal)
    • Set NOTION_CLIENT_ID, NOTION_CLIENT_SECRET, or NOTION_INTERNAL_SECRET
  • Website Crawl -- Pull content from URLs using:
    • Firecrawl (NEXT_PUBLIC_ENABLE_WEBSITE_FIRECRAWL)
    • Jina Reader (NEXT_PUBLIC_ENABLE_WEBSITE_JINAREADER)
    • WaterCrawl (NEXT_PUBLIC_ENABLE_WEBSITE_WATERCRAWL)

Batch Processing

For high-throughput scenarios:

  • Set NEXT_PUBLIC_BATCH_CONCURRENCY to control parallel request handling
  • Use BATCH_UPLOAD_LIMIT (default: 10) to control simultaneous file uploads
  • Weaviate batching: WEAVIATE_BATCH_SIZE (default: 100)

Logs and Monitoring

  • App Logs -- View request/response history per app in the Logs tab
  • Workflow Runs -- Detailed execution traces with per-node timing and I/O
  • Annotations -- Review and manage human-curated responses
  • API Request Monitoring -- Track usage, latency, and errors

Keyboard Shortcuts

Shortcut Action
Enter Send message (chat)
Shift + Enter New line in message
Ctrl/Cmd + Z Undo (workflow editor)
Ctrl/Cmd + Y Redo (workflow editor)
Delete/Backspace Delete selected node

How It Works

This section provides a high-level understanding of Dify's architecture for users who want to understand what happens behind the scenes. For deep architectural details, see the Admin Guide.

Request Flow

When you send a message to a Chat app:

User -> nginx -> Next.js (web) -> Flask API (api) -> LLM Provider
                                      |
                                 Redis (cache)
                                      |
                                PostgreSQL (state)
                                      |
                            Vector Store (RAG retrieval)
  1. The frontend sends the request to the Flask API
  2. The API authenticates and loads the app configuration
  3. If RAG is enabled, it queries the vector store for relevant chunks
  4. The prompt is assembled with context and sent to the LLM
  5. The response streams back through SSE to the frontend

RAG Pipeline

Document -> Extractor -> Cleaner -> Chunker -> Embedder -> Vector Store
  1. Extractor -- Parses file format (PDF, DOCX, etc.) into raw text
  2. Cleaner -- Removes noise (extra whitespace, boilerplate, etc.)
  3. Chunker -- Splits text into segments based on your settings
  4. Embedder -- Generates vector embeddings via your configured model
  5. Vector Store -- Stores embeddings for similarity search

At query time:

Query -> Embedder -> Vector Search -> (optional) Reranker -> Context Assembly -> LLM

Workflow Execution

The workflow engine executes DAGs using a graph engine with parallel branch support:

  1. Start at the Start node
  2. Execute nodes in topological order
  3. At parallel branches, nodes run concurrently via a thread pool (MAX_SUBMIT_COUNT)
  4. Variable Aggregator nodes wait for all upstream branches before proceeding
  5. The End node collects final outputs

Plugin Architecture

Flask API <-> plugin_daemon (Go) <-> Plugin Process (stdio JSON-RPC)

Plugins run as isolated processes managed by the Go-based plugin_daemon. Communication uses JSON-RPC over stdio, providing process isolation and language independence.


Troubleshooting

Installation Issues

Docker containers fail to start

Symptom: docker compose up -d exits with errors or containers restart in a loop.

Solutions:

  1. Check available RAM -- Dify requires at least 4 GB
  2. Verify Docker Engine and Compose versions meet requirements
  3. Check port conflicts -- ports 80, 443, 5432, 6379 must be free
  4. Review logs: docker compose logs api or docker compose logs worker

Database migration fails on startup

Symptom: API container crashes with migration errors.

Solutions:

  1. Ensure PostgreSQL is fully started before the API: check docker compose logs db
  2. Run migration manually: docker compose exec api flask upgrade-db
  3. Check DB_* environment variables match your PostgreSQL configuration

Frontend shows blank page

Symptom: http://localhost loads but shows a white screen.

Solutions:

  1. Check CONSOLE_API_URL and CONSOLE_WEB_URL in .env match your setup
  2. Verify the web container is running: docker compose ps web
  3. Check browser console for CORS errors -- update CONSOLE_CORS_ALLOW_ORIGINS

Weaviate gRPC connection failure

Symptom: Vector operations fail after upgrading Weaviate.

Solution: Weaviate v1.27+ requires gRPC on port 50051 in addition to HTTP on port 8080. Ensure both ports are exposed in your Docker Compose configuration.

Model Issues

"Model not found" or "Invalid API key"

Solutions:

  1. Verify API key in Settings
  2. Check that the model name exactly matches the provider's documentation
  3. For Azure OpenAI, ensure the deployment name matches your configured model
  4. For self-hosted models (Ollama/vLLM), verify the endpoint URL is reachable from the API container

Slow model responses

Solutions:

  1. Check NEXT_PUBLIC_TEXT_GENERATION_TIMEOUT_MS -- increase if requests time out
  2. For self-hosted models, verify GPU utilization and model loading status
  3. Reduce Max Tokens if responses are unnecessarily long
  4. For Ollama, ensure the model is loaded in memory (first request loads from disk)

Streaming not working

Solutions:

  1. Ensure your reverse proxy supports SSE (no buffering)
  2. nginx: add proxy_buffering off; to your location block
  3. Cloudflare: disable response buffering or use WebSocket mode
  4. Check NEXT_PUBLIC_SOCKET_URL if using WebSocket transport

Knowledge Base Issues

Documents stuck in "Processing"

Symptom: Uploaded documents never finish indexing.

Solutions:

  1. Check Celery worker is running: docker compose ps worker
  2. Check Redis connectivity: docker compose exec redis redis-cli ping
  3. Review worker logs: docker compose logs worker
  4. Verify embedding model is configured and has available quota

Poor retrieval quality

Solutions:

  1. Test retrieval -- Use Hit Testing to check what chunks are returned for sample queries
  2. Adjust chunk size -- Try smaller chunks (200-300 tokens) for precise answers, larger (800-1000) for context-rich answers
  3. Enable hybrid search -- Combine semantic + full-text for better recall
  4. Add a reranker -- Reranking models significantly improve precision
  5. Review chunk overlap -- 50-100 token overlap helps preserve context across boundaries

Embedding failures

Solutions:

  1. Check embedding model quota and rate limits
  2. Verify INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH is not too large for your model
  3. For large documents, processing happens in batches -- check worker logs for errors

Workflow Issues

Workflow exceeds maximum steps

Symptom: Error "Workflow execution exceeded maximum steps."

Solution: Increase WORKFLOW_MAX_EXECUTION_STEPS (default: 500) in .env, or optimize your workflow to reduce node count. Check for infinite loops in iteration nodes.

Workflow times out

Symptom: Error after 20 minutes of execution.

Solution: Increase WORKFLOW_MAX_EXECUTION_TIME (default: 1200 seconds) in .env, or break complex workflows into sub-workflows to parallelize processing.

Sub-workflow depth limit

Symptom: Error "Maximum call depth exceeded."

Solution: WORKFLOW_CALL_MAX_DEPTH defaults to 5. Flatten your sub-workflow nesting or increase the limit.

HTTP Request node fails

Solutions:

  1. Check SSRF_PROXY_HTTP_URL / SSRF_PROXY_HTTPS_URL -- all outbound requests from workflow nodes go through the SSRF proxy
  2. Verify timeout settings: HTTP_REQUEST_MAX_CONNECT_TIMEOUT (300s), HTTP_REQUEST_MAX_READ_TIMEOUT (600s)
  3. Check response size limits: HTTP_REQUEST_NODE_MAX_BINARY_SIZE (10 MB), HTTP_REQUEST_NODE_MAX_TEXT_SIZE (1 MB)

Plugin Issues

Plugin fails to install

Solutions:

  1. Check plugin_daemon container is running: docker compose ps plugin_daemon
  2. Verify PLUGIN_DAEMON_URL (default: http://127.0.0.1:5002)
  3. Check package size limit: PLUGIN_MAX_PACKAGE_SIZE (default: 15 MB / 15728640 bytes)
  4. Review daemon logs: docker compose logs plugin_daemon

Plugin cannot connect to Marketplace

Solutions:

  1. Verify MARKETPLACE_ENABLED=true in .env
  2. Check MARKETPLACE_API_URL (default: https://marketplace.dify.ai)
  3. Ensure outbound HTTPS is not blocked by firewall

API Issues

CORS errors

Solutions:

  1. Set WEB_API_CORS_ALLOW_ORIGINS to include your frontend domain
  2. Set CONSOLE_CORS_ALLOW_ORIGINS to include your console domain
  3. Use * for development (not recommended for production)

Rate limiting / "Too many requests"

Solutions:

  1. Adjust APP_MAX_ACTIVE_REQUESTS (0 = unlimited)
  2. Check APP_DEFAULT_ACTIVE_REQUESTS for the per-app default
  3. Review your LLM provider's rate limits

File upload fails

Solutions:

  1. Check file size against UPLOAD_FILE_SIZE_LIMIT (default: 15 MB)
  2. Verify storage configuration -- STORAGE_TYPE and associated credentials
  3. For S3-compatible storage, check bucket permissions and CORS

Performance Issues

Slow startup

Solution: First startup is slowest -- database migrations, model downloads, and index creation all happen. Subsequent starts are faster. The web container runs next build which can take several minutes.

High memory usage

Solutions:

  1. Redis memory: set maxmemory with an eviction policy
  2. Worker memory: limit Celery worker concurrency with -c flag
  3. Vector store: large datasets consume significant memory -- consider using a dedicated vector DB instance

Sandbox code execution timeout

Solutions:

  1. Check CODE_EXECUTION_ENDPOINT (default: http://127.0.0.1:8194)
  2. Verify CODE_EXECUTION_API_KEY matches between API and sandbox containers
  3. Adjust code size limits if hitting boundaries

Authentication Issues

"Login Locked" after failed attempts

Solution: Login lockout duration is controlled by LOGIN_LOCKOUT_DURATION (default: 86400 seconds / 24 hours). Wait for lockout to expire or reset via CLI:

docker compose exec api flask reset-password \
  --email [email removed] \
  --new-password "NewPassword123" \
  --password-confirm "NewPassword123"

Password reset token expired

Solution: Token validity is configured via RESET_PASSWORD_TOKEN_EXPIRY_MINUTES (default: 5 minutes). Request a new reset link.

Email registration disabled

Solution: Check mail configuration -- MAIL_TYPE must be set to resend or smtp with valid credentials for email-based features.

Proxy and Network Issues

Outbound requests blocked

Solutions:

  1. Configure proxy: HTTP_PROXY, HTTPS_PROXY, NO_PROXY
  2. Check SSRF_PROXY_* settings for workflow HTTP nodes
  3. SSRF proxy defaults: SSRF_DEFAULT_TIME_OUT=5, SSRF_DEFAULT_MAX_RETRIES=3

WebSocket disconnections

Solutions:

  1. Check NEXT_PUBLIC_SOCKET_URL points to your API
  2. Ensure reverse proxy supports WebSocket upgrades
  3. Verify RESPECT_XFORWARD_HEADERS_ENABLED if behind a load balancer

Tip

Most configuration problems can be diagnosed by examining container logs: docker compose logs <service_name>. Add --tail 100 to see the most recent entries.


FAQ

Q: What LLM providers does Dify support? A: Dify supports 50+ providers including OpenAI, Anthropic, Google (Gemini/PaLM), Azure OpenAI, AWS Bedrock, Cohere, Minimax, Zhipu, Baichuan, Ollama, vLLM, Xinference, LocalAI, and any OpenAI-compatible endpoint. New providers can be added via plugins.

Q: Can I run Dify completely offline / air-gapped? A: Yes. Use self-hosted models (Ollama, vLLM) for LLM inference, disable the marketplace (MARKETPLACE_ENABLED=false), and pre-install any required plugins. All core features work without internet access.

Q: What vector databases are supported? A: 25+ backends: Weaviate (default), Qdrant, pgvector, pgvecto-rs, Milvus, Chroma, Elasticsearch, OpenSearch, TiDB Vector, Oracle, OceanBase, Couchbase, Tencent, Baidu, Hologres, AnalyticDB, Alibaba Cloud MySQL, Lindorm, Upstash, VikingDB, MyScale, Tablestore, Huawei Cloud, IRIS, MatrixOne, Clickzetta, Relyt, OpenGauss, Vastbase, SeekDB. Set VECTOR_STORE in .env.

Q: How do I switch vector databases? A: Set VECTOR_STORE=<backend> in .env and restart. For existing datasets, use the CLI migration command:

docker compose exec api flask vdb-migrate --scope all

Q: What file formats can I upload to Knowledge Base? A: PDF, DOCX, TXT, Markdown (.md), HTML, CSV, XLSX (Excel), and EPUB. Maximum file size defaults to 15 MB (configurable via UPLOAD_FILE_SIZE_LIMIT).

Q: How do I back up my Dify data? A: Back up the PostgreSQL database, Redis data, your .env file, and the storage directory (uploads, files). For Docker:

docker compose exec db pg_dump -U postgres dify > backup.sql

Q: Can I use multiple models in a single app? A: Yes. In Workflow and Advanced-Chat apps, each LLM node can use a different model. This lets you use a fast/cheap model for classification and a powerful model for generation within the same flow.

Q: What languages does the UI support? A: The console supports 20+ languages including English, Chinese (Simplified/Traditional), Japanese, Korean, German, French, Italian, Spanish, Portuguese (Brazil), Russian, Turkish, Vietnamese, Thai, Arabic, Hindi, Polish, Romanian, Slovenian, Ukrainian, and Farsi.

Q: How do I set up SSO / OAuth? A: Dify supports Google OAuth out of the box. Configure GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET in .env. Enterprise edition supports additional SSO providers (SAML, OIDC).

Q: Can I customize the web app appearance? A: Yes -- you can set the app title, description, opening statement, suggested questions, and icon. For deeper customization, modify the frontend source in web/ and rebuild. Key frontend environment variables start with NEXT_PUBLIC_*.

Q: What is the difference between Chat and Advanced-Chat? A: Chat uses simple prompt orchestration (prompt + model + optional RAG). Advanced-Chat backs the chat interface with a full Workflow, giving you conditional logic, multi-step processing, tool calls, and parallel execution -- all while maintaining a conversational UX.

Q: How do I monitor API usage? A: Each app has a Monitoring tab showing request counts, token usage, latency percentiles, and user activity. For programmatic access, use the Service API's conversation and message endpoints to query usage data.

Q: What is the sandbox container for? A: The sandbox provides isolated code execution for Code nodes in workflows and agents. It runs user-submitted Python/JavaScript in a restricted environment with resource limits. Configuration: CODE_EXECUTION_ENDPOINT, CODE_EXECUTION_API_KEY.

Q: What is the ssrf_proxy and its purpose? A: The SSRF proxy is a Squid-based proxy that filters outbound HTTP requests from workflow nodes and tools. It prevents Server-Side Request Forgery attacks by blocking access to internal network addresses. All HTTP Request nodes and tool calls route through this proxy.

Q: How do I export chat/conversation data? A: Use the CLI command to export messages to JSONL format:

docker compose exec api flask export-app-messages \
  --app-id {APP_ID} --end-before "2026-01-01"

Supports --use-cloud-storage for direct S3 upload, --dry-run for previewing, and --batch-size for memory control.

Q: What happens to old workflow runs? A: Workflow run data grows over time. Use the retention CLI commands to manage it:

  • clean-workflow-runs -- Delete old runs (default: older than 30 days)
  • archive-workflow-runs -- Archive to S3-compatible storage (default: older than 90 days)
  • restore-workflow-runs -- Restore from archives All support --dry-run for safe previewing.

Q: Can I run Dify on ARM64 (Apple Silicon / AWS Graviton)? A: Yes. All official Docker images support both amd64 and arm64 architectures.

Q: How do I enable HTTPS / SSL? A: The Docker Compose setup includes a Certbot container for automatic Let's Encrypt certificates. Configure your domain in the nginx configuration and ensure ports 80 and 443 are accessible. Alternatively, terminate SSL at your own reverse proxy.

Q: What is the ETL_TYPE configuration? A: ETL_TYPE controls document parsing: dify (built-in parser, default) or Unstructured (uses the Unstructured.io API for advanced parsing). Set UNSTRUCTURED_API_URL and UNSTRUCTURED_API_KEY if using the latter.

Q: How do I configure email for password resets and invitations? A: Set MAIL_TYPE to resend (with RESEND_API_KEY) or smtp (with SMTP_SERVER, SMTP_PORT, SMTP_USERNAME, SMTP_PASSWORD, SMTP_USE_TLS). Set MAIL_DEFAULT_SEND_FROM for the sender address.

Q: Is there a way to pin or hide specific model providers and tools? A: Yes. Use position configuration in .env:

  • POSITION_PROVIDER_PINS -- Pin providers to the top
  • POSITION_PROVIDER_INCLUDES -- Whitelist (only show these)
  • POSITION_PROVIDER_EXCLUDES -- Blacklist (hide these)
  • Same pattern for tools: POSITION_TOOL_PINS, POSITION_TOOL_INCLUDES, POSITION_TOOL_EXCLUDES

Q: How much disk space do I need for Knowledge Base? A: Depends on your vector store and data volume. As a rough guide: 1 million 1536-dimensional vectors is approximately 6 GB of vector storage. Text chunks, metadata, and indexes add overhead. Monitor STORAGE_TYPE storage for uploaded files separately.

Q: How do I use Dify with a proxy? A: Set HTTP_PROXY, HTTPS_PROXY, and NO_PROXY environment variables. For LLM API calls, these are respected automatically. For workflow HTTP Request nodes, configure SSRF_PROXY_HTTP_URL and SSRF_PROXY_HTTPS_URL separately.

Q: What is multimodal input and how do I use it? A: Dify supports sending images alongside text to multimodal models (e.g., GPT-4o, Claude). Upload images via the file upload feature in chat, or via the /v1/files/upload API. The MULTIMODAL_SEND_FORMAT setting controls whether images are sent as base64 (default) or url.

Q: Can I schedule workflows to run automatically? A: Yes. Use the Schedule (Cron) trigger on Workflow apps. Define cron expressions for recurring execution. The CELERY_BEAT_SCHEDULER_TIME setting (default: 1 second) controls the scheduler's polling interval.

Q: What is the scarf_no_analytics setting? A: SCARF_NO_ANALYTICS=true disables Scarf analytics tracking (anonymous install telemetry). Set this in .env if you prefer not to send any telemetry data.


Reference

Environment Variables -- Quick Reference

Core URLs

Variable Default Description
CONSOLE_API_URL http://127.0.0.1:5001 Backend API URL for the console
CONSOLE_WEB_URL http://127.0.0.1:3000 Frontend URL for the console
SERVICE_API_URL http://127.0.0.1:5001 Service API base URL
APP_WEB_URL http://127.0.0.1:3000 Web app base URL
FILES_URL http://127.0.0.1:5001 File serving base URL

Security

Variable Default Description
SECRET_KEY -- Flask secret key (required)
INIT_PASSWORD -- Initial setup password
FILES_ACCESS_TIMEOUT 300 File URL signature timeout (seconds)
ACCESS_TOKEN_EXPIRE_MINUTES 60 JWT access token expiry
REFRESH_TOKEN_EXPIRE_DAYS 30 JWT refresh token expiry
LOGIN_LOCKOUT_DURATION 86400 Account lockout duration (seconds)

Database

Variable Default Description
DB_USERNAME postgres PostgreSQL user
DB_PASSWORD difyai123456 PostgreSQL password
DB_HOST localhost PostgreSQL host
DB_PORT 5432 PostgreSQL port
DB_DATABASE dify Database name

Redis

Variable Default Description
REDIS_HOST localhost Redis host
REDIS_PORT 6379 Redis port
REDIS_PASSWORD difyai123456 Redis password
REDIS_DB 0 Redis database number
CELERY_BROKER_URL redis://...:6379/1 Celery broker URL

Storage

Variable Default Description
STORAGE_TYPE opendal Storage backend (opendal, s3, azure-blob, etc.)
OPENDAL_SCHEME fs OpenDAL scheme (fs, s3, gcs, etc.)
OPENDAL_FS_ROOT storage Local filesystem root for OpenDAL

Vector Store

Variable Default Description
VECTOR_STORE weaviate Vector database backend
WEAVIATE_ENDPOINT http://localhost:8080 Weaviate endpoint
WEAVIATE_API_KEY -- Weaviate API key
WEAVIATE_BATCH_SIZE 100 Weaviate batch size

Execution Limits

Variable Default Description
WORKFLOW_MAX_EXECUTION_STEPS 500 Max workflow steps
WORKFLOW_MAX_EXECUTION_TIME 1200 Max workflow time (seconds)
WORKFLOW_CALL_MAX_DEPTH 5 Max sub-workflow nesting
MAX_VARIABLE_SIZE 204800 Max variable size (bytes)
APP_MAX_EXECUTION_TIME 1200 Max app execution time

Logging

Variable Default Description
LOG_LEVEL INFO Logging level
LOG_FILE -- Log file path (empty = stdout)
LOG_FILE_MAX_SIZE 20 Max log file size (MB)
LOG_FILE_BACKUP_COUNT 5 Log rotation count
LOG_TZ UTC Log timezone

Supported Vector Stores -- Complete List

Backend Entry Point Key Dependency
Weaviate weaviate weaviate-client==4.20.5
Qdrant qdrant qdrant-client==1.9.0
pgvector pgvector pgvector==0.4.2
pgvecto-rs pgvecto-rs pgvecto-rs[sqlalchemy]~=0.2.2
Milvus milvus pymilvus~=2.6.12
Chroma chroma chromadb==0.5.20
Elasticsearch elasticsearch elasticsearch==8.14.0
Elasticsearch (Japanese) elasticsearch-ja elasticsearch==8.14.0
OpenSearch opensearch opensearch-py==3.1.0
TiDB Vector tidb_vector tidb-vector==0.0.15
TiDB on Qdrant tidb_on_qdrant qdrant-client==1.9.0
Oracle oracle oracledb==3.4.2
OceanBase oceanbase pyobvector~=0.2.17
SeekDB seekdb pyobvector~=0.2.17
Couchbase couchbase couchbase~=4.6.0
Tencent tencent tcvectordb~=2.1.0
Baidu baidu pymochow==2.4.0
Hologres hologres holo-search-sdk>=0.4.2
AnalyticDB analyticdb alibabacloud_gpdb20160503~=5.2.0
Alibaba Cloud MySQL alibabacloud_mysql mysql-connector-python>=9.3.0
Lindorm lindorm opensearch-py==3.1.0
Upstash upstash upstash-vector==0.8.0
VikingDB vikingdb volcengine-compat~=1.0.0
MyScale myscale clickhouse-connect~=0.15.0
Tablestore tablestore tablestore==6.4.4
Huawei Cloud huawei_cloud elasticsearch==8.14.0
IRIS iris intersystems-irispython>=5.1.0
MatrixOne matrixone mo-vector~=0.1.13
Clickzetta clickzetta clickzetta-connector-python>=0.8.102
Relyt relyt --
OpenGauss opengauss --
Vastbase vastbase pyobvector~=0.2.17

CLI Commands -- Quick Reference

All CLI commands run via Flask. In Docker: docker compose exec api flask <command>.

Account Management

Command Description
reset-password --email <e> --new-password <pw> --password-confirm <pw> Reset account password
reset-email --email <current> --new-email <new> --email-confirm <new> Change account email
create-tenant --email <e> --name <name> [--language en-US] Create workspace + account

Database and System

Command Description
upgrade-db Run database migrations
reset-encrypt-key-pair Reset workspace encryption keys (invalidates all stored LLM credentials)
convert-to-agent-apps Convert legacy Agent Assistant apps to Agent App type
fix-app-site-missing Repair apps with missing site records

Vector Database

Command Description
vdb-migrate [--scope all] Migrate vectors between backends
add-qdrant-index [--field metadata.doc_id] Add index to Qdrant collections
old-metadata-migration Migrate legacy metadata format

Data Retention

Command Description
clean-workflow-runs --before-days 30 [--dry-run] Delete old workflow runs
archive-workflow-runs --before-days 90 [--dry-run] Archive runs to S3
restore-workflow-runs --tenant-ids <id> [--run-id <id>] Restore archived runs
delete-archived-workflow-runs --tenant-ids <id> [--dry-run] Delete archived runs from DB
clean-expired-messages [--dry-run] Clean old messages
export-app-messages --app-id <id> --end-before <date> Export messages to JSONL.GZ
clear-free-plan-tenant-expired-logs --days 30 Clear expired tenant logs
cleanup_orphaned_draft_variables [--dry-run] Remove orphaned draft variables

Storage

Command Description
clear-orphaned-file-records [-f] Remove DB records for missing files
remove-orphaned-files-on-storage [-f] Delete storage files without DB records
file-usage [--file-id <id>] [--key <key>] [--json] Query file reference locations
migrate-oss [--source opendal] [--dry-run] Migrate files between storage backends

Plugins

Command Description
migrate-data-for-plugin Migrate data for plugin system
extract-plugins [--output_file plugins.jsonl] Extract plugin definitions
install-plugins [--input_file plugins.jsonl --workers 100] Batch install plugins
install-rag-pipeline-plugins [--workers 100] Install RAG pipeline plugins
setup-system-tool-oauth-client --provider <name> --client-params <json> Configure tool OAuth
setup-system-trigger-oauth-client --provider <name> --client-params <json> Configure trigger OAuth
setup-datasource-oauth-client --provider <name> --client-params <json> Configure datasource OAuth

API Endpoints -- Quick Reference

Service API (/v1/*)

Method Path Description
POST /v1/chat-messages Send chat message
POST /v1/completion-messages Send completion request
POST /v1/workflows/run Run a workflow
GET /v1/workflows/run/{id} Get workflow run status
POST /v1/files/upload Upload a file
GET /v1/messages List messages
GET /v1/conversations List conversations
DELETE /v1/conversations/{id} Delete conversation
POST /v1/conversations/{id}/name Rename conversation
POST /v1/audio-to-text Speech to text
POST /v1/text-to-audio Text to speech
GET /v1/parameters Get app parameters
GET /v1/meta Get app metadata

System Endpoints

Method Path Description
GET /health Health check
GET /version API version
GET /init Setup status
GET /ping Liveness probe
GET /db-pool-stat Database pool statistics
GET /threads Active thread count