Dify self-hosted runs on a CPU-only VPS, and its official minimum of 2 CPU cores and 4 GiB of RAM is a real floor, not a comfortable size. We ran the official Docker Compose stack of Dify 1.17.1 on exactly that, 2 vCPUs and 4 GiB with no swap and no GPU, and with its 15 long-running containers idle, the server used 2,257 MB of memory before any model or document was added. Dify is a platform for building AI apps such as chatbots, agents, workflows and RAG search over your own documents, and self-hosting means the whole stack runs on your server.
With Ollama and the nomic-embed-text embedding model added, an 84 KB document was searchable 92 seconds after upload, and ten technical documents (2.2 MB of text) took 42.5 minutes. A 1.5B chat model also fit, but got only some answers right. On our VPS hosting plans, that makes a VPS Mini (4 shared vCPU, 4 GB RAM) the smallest sensible size for Dify, and a VDS Small (4 dedicated vCPU, 8 GB) the starting point for a team that wants local models.
Key facts, checked on 2026-10-17:
- Dify 1.17.1, released on 10 September 2026, was the latest release (GitHub releases).
- The official minimum is 2 CPU cores and 4 GiB of RAM, with Docker 19.03 and Docker Compose 2.24.0 or later on Linux (Dify Docker Compose docs).
- According to the same guide,
docker compose up -dstarts 16 containers: 7 core services, 8 dependencies and 1 task that sets file permissions and exits. We counted the same 16. - The licence is "a modified version of the Apache License 2.0": a multi-tenant service needs Dify's written permission, and the frontend logo must stay (LICENSE).
- 1.17.1 moves the bundled Weaviate vector database from 1.27.0 to 1.39.2, and the release notes say skipping minor versions "is unsupported".
Dify self-hosted requirements: the minimum vs what we measured
Dify's Docker Compose guide lists CPU, RAM and software versions. This is how those numbers looked on a running server.
| Resource | Dify docs minimum | Measured on Dify 1.17.1 | What we would plan |
|---|---|---|---|
| CPU | 2 cores | 2 vCPUs ran it; both were busy (up to 198%) while Ollama embedded documents | 4 vCPU, dedicated if you run local models |
| RAM | 4 GiB | 2,257 MB idle, 3,172 MB peak while indexing, 3,867 MB with a 0.5B chat model right after indexing | 4 GB with cloud models, 8 GB or more for local chat |
| Docker | 19.03 or later | 26.1.5 from Debian 13's packages | The Debian package worked |
| Docker Compose | 2.24.0 or later | 2.26.1 from Debian 13's packages | 2.24.0 or later; Debian's 2.26.1 also handled the override file below |
| Disk | No figure given | 7.98 GB of Dify images, 13.55 GB with Ollama; after tests 257 MB database, 72 MB vectors, 1.6 GB for three models | VPS Mini's 80 GB NVMe leaves room for documents and more models |
A 2 GB server is out: the four Python services alone hold 1.8 GB at idle. Ollama is the big extra on disk, with a 5.57 GB image, so leave it out if you only use cloud models.
How much RAM Dify uses, container by container
Dify is not one program. One to three minutes after creating the admin account, with no plugin or knowledge base yet, we read docker stats --no-stream three times, a minute apart. The table shows the middle reading.
| Container | What it does | Idle RAM |
|---|---|---|
| worker_beat | Starts timed background jobs | 441 to 503 MiB |
| api | Main backend: console, apps, API | 477 MiB |
| api_websocket | Live co-editing of workflows (optional) | 428 MiB |
| worker | Background jobs, including indexing | 426 MiB |
| web | Web interface (Next.js) | 124 MiB |
| sandbox | Runs Code nodes in isolation | 123 MiB |
| agent_backend | Runtime for Dify's newer agent feature | 113 MiB |
| db_postgres | PostgreSQL 15: accounts, apps, chats, chunk text | 76 MiB |
| weaviate | Vector database for knowledge search | 69 MiB |
| agent_ssrf_proxy, ssrf_proxy | Proxies that block calls to internal addresses | 32 + 23 MiB |
| local_sandbox | Where the agent runs commands | 27 MiB |
| plugin_daemon | Runs plugins, including model providers | 23 MiB empty, 76 to 271 MiB with the Ollama plugin |
| redis | Cache and job queue | 11 MiB |
| nginx | Front door on ports 80 and 443 | 10 MiB |
| All 15 | free -m: 2,257 MB used, 1,838 MB available | 2,464 MiB |
The four Python services at the top each load the whole Dify backend, so they hold 1.8 GB before anyone logs in. They also keep memory they grow into: after our big indexing run the worker peaked at 755 MiB during the next chat test and dropped back to 420 MiB only after we restarted the stack. If Dify shares the server with other apps, our RAM guide for self-hosted apps helps you add things up.
One container is easy to drop. api_websocket only serves live co-editing, and Dify's environment reference gives its browser address, NEXT_PUBLIC_SOCKET_URL, a default of ws://localhost, so on a remote server it needs extra setup before it is any use. With collaboration off, idle use fell from 2,257 MB to 1,862 MB, with Ollama and its plugin installed.
How we tested
- A Debian 13 container on our Amsterdam lab host (AMD EPYC 7742), limited to 2 vCPUs and 4 GiB with swap off, shared with other test labs, so treat times as a guide.
- Dify 1.17.1, Docker 26.1.5 and Compose 2.26.1 from Debian's packages, Ollama 0.40.6 (released 16 October 2026), the Ollama plugin 1.0.2 and nomic-embed-text, a 274 MB embedding model.
- Ten IETF RFCs as plain text from the RFC Editor (HTTP, TLS 1.3, TCP, SMTP, SPF, DKIM): 2.2 MB, 296,652 words.
- The web interface's chunk defaults: blank line (
\n\n) as delimiter, maximum chunk length 1,024, overlap 50.
In our nested containers, Ollama saw all 8 host cores and ran 8 threads on 2 vCPUs, which made embedding six to seven times slower. A KVM VPS shows its real vCPU count, so we pinned the model to 2 threads.
How long Dify takes to index documents on a CPU
RAG (retrieval-augmented generation) means the app searches your documents and hands the best passages to the language model together with the question. Dify first cuts each document into chunks, and an embedding model turns every chunk into a vector, a list of numbers that describes its meaning. On a CPU, that embedding step is the slow part.
| Test | Chunks and tokens | Time until searchable | Peak RAM, whole server |
|---|---|---|---|
| RFC 9111 alone (84 KB), High Quality mode | 454 chunks, 18,620 tokens | 92 s | 2,672 MB |
| All ten (2.2 MB), default worker settings | 3 of 10 documents finished | Stalled after 13 min: 2 errors, 5 stuck | Not measured |
All ten, CELERY_WORKER_AMOUNT=2 | 10,300 chunks, 483,206 tokens | 42.5 min, about 190 tokens per second | 3,172 MB |
| All ten, Economical mode | 10,300 chunks, no vectors | 50 s | 3,256 MB |
| RFC 9111 uploaded again | 454 chunks | 4 s | Not measured separately |
Dify reuses stored embeddings for identical text, hence the 4-second re-upload; we emptied that cache before the timed runs. Ollama peaked at 198% CPU, so both vCPUs were busy, and a search took 1.0 to 2.8 seconds because each question is embedded on the CPU too.
Economical mode stores 10 keywords per chunk instead of vectors. It indexed 51 times faster but found far less: for three questions with clear answers, High Quality returned a passage from the right RFC every time, Economical once. A High Quality knowledge base cannot be switched back to Economical later (Dify docs on index methods).
Why a batch upload stalled, and the one-line fix
Dify's worker is a Celery process, a Python job queue, and CELERY_WORKER_AMOUNT sets how many documents it indexes at once: 4 by default. Each document gets 10 embedding threads (max_workers = 10 in Dify's indexing_runner.py), and every thread holds a database connection while it waits for the model.
Ollama answers one request at a time (OLLAMA_NUM_PARALLEL defaults to 1, per the Ollama FAQ). On 2 cores, 40 threads waited on 40 connections, exactly the default pool of 30 plus 10 overflow. Two documents and a scheduled job failed:
# from the worker log (docker compose logs worker)
QueuePool limit of size 30 overflow 10 reached, connection timed out, timeout 30.00
Five more documents stayed on "waiting" or "indexing" for good, with no error shown. The fix is one line in .env:
# as the dify user, in ~/dify/docker
sed -i 's/^CELERY_WORKER_AMOUNT=.*/CELERY_WORKER_AMOUNT=2/' .env
docker compose up -d worker
Dify's environment reference already says to lower this "on constrained VMs". With 2, all ten files indexed without an error, and single documents took no longer than in the stalled run (RFC 7208 about 7 minutes both times), because Ollama was the queue anyway. Re-upload any documents that failed before.
Why ten files became 10,300 chunks
Dify's general chunking cuts at every delimiter and never joins short pieces (we checked fixed_text_splitter.py), so every RFC paragraph became a chunk of 47 tokens on average. That hurts answers. Top K, the number of passages Dify hands to the model, is 3 by default. For "What is the maximum number of DNS lookups during an SPF check?" the passage with the answer (10) ranked fifth, and the first hit was the bare heading "4.6.4. DNS Lookup Limits".
For text with short paragraphs, try a rarer delimiter or parent-child mode (see the chunking guide), and test with real questions.
Can Dify run a local chat model in 4 GB without a GPU?
A small one, just. We built a chat app on the ten-RFC knowledge base with two Qwen 2.5 models and asked three questions: the status code for a request that is too large (413), how long an SMTP client waits for the first 220 greeting (5 minutes), and the SPF lookup limit (10).
| Model and setup | Peak RAM, whole server | Time to first word | Answers |
|---|---|---|---|
| qwen2.5:0.5b (397 MB), stock settings, right after the 42-minute indexing run | 3,867 MB of 4,096 | 34.8 s cold, 5.8 to 11.8 s warm | 413 right; 5 minutes, wrong reason; SPF wrong ("two") |
| qwen2.5:0.5b after a restart, collaboration off | 2,506 MB | 17.4 s cold, 3.4 to 7.6 s warm | The same three answers |
| qwen2.5:1.5b (986 MB), collaboration off, set as default model | 3,246 MB (3,714 MB while the 0.5B model was also loaded) | 5.1 to 27.4 s | First three: 413 and 5 minutes right, SPF wrong; three new questions: 1 right, 1 close, 1 wrong |
Once the first word appeared, the 1.5B model wrote about 10 tokens per second and the 0.5B model up to 26. Asked in the RFC's own words ("DNS-querying terms"), the 1.5B model answered 10, so retrieval lost the SPF question, not the model.
One trap: Dify titles each new conversation with the workspace's default model, which is the first LLM you add. Ours was still the 0.5B model, so each chat loaded two models and one answer took 67 seconds. Set the default to your app's model.
On 4 GB, local chat is a demo. Use a cloud model there, or a VDS plan with 8 GB or more for a 3B model. Our guide to running 3B to 8B models on a CPU server lists RAM and speed per model size. A small local model also ran in our Odysseus AI workspace test on CPU.
Which server size and city for Dify
| Your situation | Plan | City | Why |
|---|---|---|---|
| Dify with cloud models, or local embeddings for a modest knowledge base | VPS Mini: 4 shared vCPU, 4 GB RAM, 80 GB NVMe | The one nearest your users | 2.3 GB idle and 3.2 GB peak while indexing in our test on 2 vCPUs; Mini has twice the vCPUs |
| A team using local embeddings plus a 1.5B to 3B chat model | VDS Small: 4 dedicated vCPU, 8 GB, 240 GB NVMe | The one nearest your team | Room for the chat model next to Dify; dedicated vCPUs keep indexing times steady |
| Large document sets, several apps, a 7B to 8B local model | VDS Medium: 8 dedicated vCPU, 16 GB, 480 GB NVMe | The one nearest your users | Twice the cores for embedding and answers, memory for a 5 GB model |
| Company documents that must stay in the EU | Any of the three above | Amsterdam or Dublin | Both cities are in the EU, where the GDPR applies directly |
| Users in Kosovo, Albania or North Macedonia | Any of the three above | Prishtina | Closest to the Balkans; Skopje is about 3 ms away on our own network |
VPS Nano (1 GB) and VPS Micro (2 GB) are smaller than Dify's idle stack, so we do not suggest them for Dify. In our ping.pe measurements of 6 October 2026, published on our location pages, the Amsterdam server answered Frankfurt in 6.6 ms and London in 6.7 ms, and the Prishtina server answered Vienna in 18.6 ms and Frankfurt in 27.8 ms.
Every plan has NVMe, unmetered traffic and its own IPv4 and IPv6, and an upgrade from the client area needs only a short reboot. Availability by city is on the plans page.
How to self-host Dify with Docker Compose, step by step
Docker Compose starts a set of containers from one file, and Dify ships that file. These are our lab steps on Debian 13. Start from a server prepared as in our Debian 13 security guide; ports published by Docker skip ufw rules, as our Docker on a VPS guide explains.
Step 1. Install Docker, Compose, git and jq, and create a user for Dify:
# as root
apt update
apt install -y docker.io docker-compose git curl jq
adduser --disabled-password --gecos "" dify
usermod -aG docker dify
docker --version
docker compose version
We saw Docker version 26.1.5+dfsg1 and Docker Compose version 2.26.1-4. Members of the docker group control every container, so treat the dify user like root.
Step 2. Download a fixed version:
# as the dify user (su - dify)
git clone --depth 1 --branch 1.17.1 https://github.com/langgenius/dify.git
cd dify/docker
Step 3. Set your own secrets before the first start, because PostgreSQL keeps the password it was created with. The example file ships with shared defaults such as difyai123456. This script replaces them all and sets the worker fix; its last line should print 0:
# as the dify user, in ~/dify/docker
cp .env.example .env
new() { openssl rand -hex 24; }
DBP=$(new); RP=$(new); WK=$(new); SBK=$(new)
AGENTKEY=$(openssl rand -base64 32 | tr '+/' '-_' | tr -d '=')
sed -i \
-e "s|^SECRET_KEY=.*|SECRET_KEY=$(openssl rand -base64 42)|" \
-e "s|^INIT_PASSWORD=.*|INIT_PASSWORD=$(openssl rand -hex 12)|" \
-e "s|^DB_PASSWORD=.*|DB_PASSWORD=$DBP|" \
-e "s|^REDIS_PASSWORD=.*|REDIS_PASSWORD=$RP|" \
-e "s|^CELERY_BROKER_URL=.*|CELERY_BROKER_URL=redis://:$RP@redis:6379/1|" \
-e "s|^WEAVIATE_API_KEY=.*|WEAVIATE_API_KEY=$WK|" \
-e "s|^WEAVIATE_AUTHENTICATION_APIKEY_ALLOWED_KEYS=.*|WEAVIATE_AUTHENTICATION_APIKEY_ALLOWED_KEYS=$WK|" \
-e "s|^CODE_EXECUTION_API_KEY=.*|CODE_EXECUTION_API_KEY=$SBK|" \
-e "s|^SANDBOX_API_KEY=.*|SANDBOX_API_KEY=$SBK|" \
-e "s|^PLUGIN_DAEMON_KEY=.*|PLUGIN_DAEMON_KEY=$(new)|" \
-e "s|^PLUGIN_DIFY_INNER_API_KEY=.*|PLUGIN_DIFY_INNER_API_KEY=$(new)|" \
-e "s|^DIFY_AGENT_API_TOKEN=.*|DIFY_AGENT_API_TOKEN=$(new)|" \
-e "s|^DIFY_AGENT_SERVER_SECRET_KEY=.*|DIFY_AGENT_SERVER_SECRET_KEY=$AGENTKEY|" \
-e "s|^CELERY_WORKER_AMOUNT=.*|CELERY_WORKER_AMOUNT=2|" \
.env
chmod 600 .env
grep -c "difyai123456\|dify-sandbox\|dev-only\|WVF5YTha\|lYkiYYT6\|QaHbTe77\|MDEyMzQ1" .env
The Redis password also sits inside CELERY_BROKER_URL, and the Weaviate and sandbox keys appear twice, so one value serves each pair. The agent key is made differently because DIFY_AGENT_SERVER_SECRET_KEY must decode to exactly 32 bytes; a 48-character hex string broke our first attempt.
Step 4. The plugin daemon publishes port 5003 (remote plugin debugging) on every interface. Setting EXPOSE_PLUGIN_DEBUGGING_PORT=127.0.0.1:5003 in .env makes the api container restart in a loop, so use an override file next to the main one instead; Compose reads it automatically. Ours keeps port 5003 local and adds Ollama without publishing its port:
# ~/dify/docker/docker-compose.override.yaml, owned by the dify user
services:
plugin_daemon:
ports: !override
- "127.0.0.1:5003:5003"
ollama:
image: ollama/ollama:0.40.6
restart: always
volumes:
- ./volumes/ollama:/root/.ollama
!override replaces the port list instead of adding to it (Compose merge rules); Debian's Compose 2.26.1 accepted it, and docker compose config showed the port bound to 127.0.0.1. Leave out ollama if you only use cloud models.
Step 5. Start everything:
# as the dify user, in ~/dify/docker
docker compose up -d
docker compose ps
The first image pull took 115 seconds for us, and the API answered 110 seconds after up -d. The api container runs its database migrations at start (MIGRATION_ENABLED=true in .env), and until it is ready, API calls return a 502 error.
Every service should read Up, and init_permissions Exited (0). In PORTS, nginx shows 0.0.0.0:80->80/tcp and 0.0.0.0:443->443/tcp, plugin_daemon 127.0.0.1:5003->5003/tcp, and ollama only 11434/tcp, meaning not published.
Step 6. Claim the admin account at once: whoever opens /install first becomes the owner, hence INIT_PASSWORD. Read it:
# as the dify user, in ~/dify/docker
grep ^INIT_PASSWORD= .env
Open http://YOUR_SERVER_IP/install, enter it, and create the admin with a password of at least 8 characters with letters and numbers. Through Dify's console API, creating the admin without the init password returned 401 Unauthorized, and with it success. Before real use, add a reverse proxy with a TLS certificate.
Connect Ollama to Dify for local embeddings
Ollama runs open models on your own server, and Dify talks to it through a plugin. Pull the embedding model first:
# as the dify user, in ~/dify/docker
docker compose exec ollama ollama pull nomic-embed-text
docker compose exec ollama ollama list
The list should show nomic-embed-text:latest at 274 MB. After the first request, docker compose logs ollama | grep n_threads shows how many threads Ollama uses. Only if that differs from your vCPU count, pin it (2 here):
# as the dify user, in ~/dify/docker
printf 'FROM nomic-embed-text\nPARAMETER num_thread 2\n' > Modelfile.embed
docker compose cp Modelfile.embed ollama:/tmp/Modelfile.embed
docker compose exec ollama ollama create nomic-embed-text -f /tmp/Modelfile.embed
In Dify, install the Ollama plugin by langgenius from the Marketplace. Then add a model under Ollama in the model provider settings: name nomic-embed-text, type Text Embedding, base URL http://ollama:11434 without /api, context size 2048. We did both through Dify's console API, which these forms call: the plugin installed in 8 seconds, and the model saved in 16 seconds, including its first load.
Then create a High Quality knowledge base with that model. Because Dify reaches Ollama by service name, you skip OLLAMA_HOST=0.0.0.0 and an open Ollama API with no password.
Make a small Dify server lighter
This turns off collaboration mode and three outside calls. Weaviate reports its version, host system, modules and object count every 24 hours, and its docs say the data may be used "to identify potential customers" (Weaviate telemetry). Dify's compose file also sets NEXT_TELEMETRY_DISABLED to 0 for the web container, and the console checks updates.dify.ai for new versions.
Run down first: once collaboration leaves COMPOSE_PROFILES, Compose stops seeing that container and leaves it running, as it did for us.
# as the dify user, in ~/dify/docker
docker compose down
sed -i \
-e 's/^COMPOSE_PROFILES=.*/COMPOSE_PROFILES=${VECTOR_STORE:-weaviate},${DB_TYPE:-postgresql}/' \
-e 's/^ENABLE_COLLABORATION_MODE=.*/ENABLE_COLLABORATION_MODE=false/' \
-e 's/^WEAVIATE_DISABLE_TELEMETRY=.*/WEAVIATE_DISABLE_TELEMETRY=true/' \
-e 's/^CHECK_UPDATE_URL=.*/CHECK_UPDATE_URL=/' \
.env
echo 'NEXT_TELEMETRY_DISABLED=1' >> .env
docker compose up -d
Afterwards docker compose ps listed 15 services with Ollama and no api_websocket, and apps answered as before. The Marketplace stays on for plugins.
Troubleshooting self-hosted Dify: the errors we hit
Every row below happened in our lab on Dify 1.17.1. docker compose logs followed by the service name shows the error text.
| What you see | Cause | Fix |
|---|---|---|
agent_backend restarts in a loop with must decode to exactly 32 decoded bytes | DIFY_AGENT_SERVER_SECRET_KEY has the wrong length, such as 48 hex characters | Generate it from 32 random bytes, as the script in step 3 does |
api restarts with PLUGIN_REMOTE_INSTALL_PORT must be a bare port number | EXPOSE_PLUGIN_DEBUGGING_PORT was set to 127.0.0.1:5003 | Keep the value from .env.example and bind the port with the override file in step 4 |
| API calls return 502 in the first minutes | The api container is still running database migrations | Wait; ours answered 110 seconds after up -d |
init_permissions shows Exited (0) | A one-time task that sets file permissions | Nothing, this is expected |
Documents stay on "waiting" or "indexing", or fail with QueuePool limit of size 30 overflow 10 reached | 4 documents at once with 10 threads each fill the 40 database connections while CPU embedding is slow | CELERY_WORKER_AMOUNT=2, then re-upload the failed documents |
api_websocket still runs after you turned collaboration off | collaboration left COMPOSE_PROFILES before docker compose down | docker compose --profile collaboration rm -sf api_websocket |
| Each chat loads a second model, and one answer took 67 seconds | Dify names conversations with the workspace's default model | Set the default model to your app's model |
| The answer is in your documents, but the reply is wrong | Short chunks pushed the right passage below the top 3 that reach the model | Try a rarer delimiter or parent-child chunks, and test with real questions |
Where self-hosted Dify stores your documents (GDPR)
Everything sits in ~/dify/docker/volumes: PostgreSQL with accounts, apps, chats and the text of every chunk, Weaviate's vectors, uploads and plugins. After our tests the database took 257 MB and Weaviate 72 MB.
With Ollama, prompts and documents stay on the server; with a cloud model, questions and retrieved passages go to the provider. When you copy volumes for safekeeping, copy .env with it, because it holds the database password and the other keys the stack was created with. The keys that decrypt saved model API credentials sit in volumes/app/storage/privkeys, per Dify's source, so keep the folder whole. Amsterdam and Dublin keep documents in the EU, and our CLOUD Act checklist for European hosting lists what a data protection officer will ask.
How to update Dify without breaking vector search
A fresh 1.17.1 install needs nothing here. For an older install updated in place, the release notes warn that pulling and restarting "can silently and permanently break vector search". Dify's Weaviate upgrade path lists 13 steps, one minor version at a time, after a copy of ./volumes/weaviate; we did not run it.
After every update, compare .env.example with your .env: 1.16.1, for example, added the required DIFY_AGENT_API_TOKEN.
Frequently asked questions
What are the minimum requirements for Dify self-hosted?
Dify's docs ask for at least 2 CPU cores, 4 GiB of RAM, Docker 19.03 and Docker Compose 2.24.0 on Linux. In our test of Dify 1.17.1 on exactly 2 vCPUs and 4 GiB, the idle stack used 2,257 MB, leaving about 1.8 GB for plugins, models and indexing. Dify's images took 7.98 GB of disk, or 13.55 GB with Ollama.
How much RAM does Dify use?
The official Docker Compose stack of Dify 1.17.1 keeps 15 containers running and used 2,257 MB at idle in our lab, about 1.8 GB of it in four Python services. Indexing ten documents with local embeddings peaked at 3,172 MB. With collaboration mode off, idle use fell to 1,862 MB, with Ollama and its plugin installed.
Can Dify run on a 2 GB VPS?
No. In our test of Dify 1.17.1, the api, worker, worker_beat and api_websocket services alone held about 1.8 GB before anyone logged in, and the whole idle stack used 2,257 MB. Plan 4 GB as the floor, and 8 GB or more if you also want a local chat model.
Can Dify run without a GPU?
Yes. Dify needs no GPU and can use cloud models through an API. With Ollama on 2 vCPUs, nomic-embed-text indexed 483,206 tokens in 42.5 minutes. A 1.5B chat model ran in 4 GB but answered only some test questions correctly, so plan 8 GB or more for local chat.
How long does Dify take to index documents on a CPU?
On 2 vCPUs with nomic-embed-text, one 84 KB document took 92 seconds and ten documents with 2.2 MB of text took 42.5 minutes, about 190 tokens per second. Set CELERY_WORKER_AMOUNT=2 first: with the default of 4, the batch hit database pool timeouts and only 3 of 10 documents finished.
Is self-hosted Dify free for commercial use?
Mostly. The licence is Apache 2.0 with two conditions: a multi-tenant service, where one tenant is one workspace, needs Dify's written permission, and the logo and copyright in the frontend must stay. Using Dify inside your company or behind your own product is allowed.
Start with the stack, add models later
A 4 GB server runs Dify well enough to build apps, index a few hundred pages and answer with a cloud model, once the worker is set to 2. Local chat models want 8 GB and dedicated cores. RS Computers runs KVM VPS and VDS servers in Amsterdam, Dublin and Prishtina: pick a size and a city on our VPS hosting plans page, or message us on Telegram for help sizing a server.