Dify Celery workers and queue backlog monitoring

Dify runs indexing and workflow work through Celery workers, so a backlog shows up as slow or stalled documents and runs. This page covers how to scale workers, watch the dataset queue, and shut down cleanly during deploys.

On this page

Why Dify Celery workers and queue backlog monitoring decide how fast your knowledge bases and workflows respond

When documents index slowly or workflow runs sit in a queue, the cause is usually background work that is not keeping up. Celery workers execute those background jobs, and queue monitoring plus worker sizing decide whether they keep pace with your load. In a self-hosted Dify, the Docker Compose layout starts a separate worker container alongside the api container, and it is the one that picks up indexing and other asynchronous tasks. Teams usually need to look at this layer when a bulk document upload takes far longer than expected, when several knowledge bases are being indexed at once, or when workflow runs that depend on background processing start to lag behind user requests.

The researched facts for this topic do not name the Celery queues Dify uses, state a backlog threshold, or describe the exact worker concurrency settings for each release. Confirm those details against the version you run, by checking the Dify Compose files and environment reference for that release and by reading the release notes for any change to queue names. Before you change worker counts, record what the backlog looks like at normal and peak load so you can tell whether a change helped. The Dify environment variable reference is the first place to check which worker-related settings your version exposes.

Scaling workers also has side effects on the rest of the stack. Each worker consumes CPU, memory and connections to PostgreSQL and Redis, and embedding and indexing jobs call external model endpoints, so more workers can move the bottleneck rather than remove it. Plan the worker count together with database connection limits, model provider rate limits and the sizing of the vector store. Shutdown behavior matters too: during a deploy, a worker that is stopped in the middle of a job can leave that job incomplete, so the way you restart workers is part of the same decision.

Scaling workers for indexing load versus workflow load

Indexing work starts when a document is uploaded or a knowledge base is synced. The worker parses the file, splits it into chunks, sends each chunk to the embedding model, and writes vectors to the vector store and metadata to PostgreSQL. One large file produces many embedding calls, so the load arrives in bursts and depends heavily on outbound calls and vector writes, with moderate CPU for parsing.

  • Queue pressure: A single bulk upload can enqueue many indexing jobs at once, which delays any workflow job waiting in the same pool.
  • CPU: Parsing and chunking are CPU work, most noticeable with large PDFs and office files.
  • Memory: Large files are held in memory during parsing, so peak memory grows with file size and the number of parallel jobs. Confirm the peak with a test upload of your largest expected file.
  • Outbound throughput: Embedding speed is often capped by the provider's rate limits or the capacity of a local model server, so extra workers can hit those limits sooner.

During a representative bulk import, check queue depth and embedding endpoint error rates before you change the worker count.

Worker and queue settings and when each fits

This table compares the main worker, queue and shutdown choices for a self-hosted Dify and states when each one fits and what it costs in return. Use it to decide what to change first, then confirm exact variable names and defaults in the environment variable reference for your version before editing anything.

SettingWhen it fitsTrade-offConfirm before changing
Number of worker containersIndexing batches or workflow runs wait for a free worker, and the backlog clears slowly after uploads or bulk importsMore containers raise CPU, memory and database connections on the same host, and can slow the api and web services if the host is undersizedHost CPU and RAM headroom, and the worker service name in your Compose file
Worker concurrency per containerOne container has spare CPU but jobs still queue, so more parallel tasks per container may helpHigher concurrency multiplies memory use and parallel calls to model providers and the vector store, which can trigger provider rate limitsThe concurrency setting for your version and its default value
Dedicated Redis for DifyDify shares a Redis instance with other applications, or queue traffic must be isolated from cache traffic for monitoring and recoveryA dedicated instance adds one more service to back up, patch and monitor, and needs its own memory sizingWhether Redis is external or bundled, and the Redis connection variables in use
Shared Redis with key prefixesA small deployment has spare capacity and one team operates both the Dify and other workloadsShared instances mean a memory spike or restart in one application affects the Dify queue, and key naming must avoid collisionsRedis memory limits, eviction policy and the Celery broker database index
Dataset queue monitor enabledYou need to know when indexing jobs stall before users report missing knowledge base contentMonitoring adds a periodic check and an alert path that must be tested, and an unmonitored queue fails silentlyThe monitor variable name, its check interval and whether it is on by default
Alert recipientsA named on-call group or shared operations mailbox owns indexing healthToo many recipients create noise, and a single personal address leaves alerts unread during leave or role changesMail delivery is working for alert messages, see the email delivery configuration topic
Warm shutdown grace periodDeploys restart workers while long indexing or workflow tasks are running, and you want running tasks to finishA longer grace period slows deploys and can hold up rollbacks, while a short one can interrupt tasks and leave items to retryThe stop grace period set in Compose or Kubernetes and the worker shutdown behavior in your version

Setting up worker scaling and queue monitoring in order

This sequence confirms the platform can run workers, records what normal queue depth looks like, and then changes one thing at a time so you can see whether scaling and deploys behave as expected. Each step ends with a check you can run on the host.

  1. Confirm the Docker Compose version

    The platform engineer confirms that the host runs Docker Compose 2.24.0 or later, the minimum that the self-hosting docs give for the Compose deployment, before changing any worker settings. Run docker compose version on the host that runs the stack and compare the output with that minimum. Then run docker compose ps to confirm that the api, worker, web, plugin daemon, PostgreSQL, Redis and the other core services are running. The step is done when the version is 2.24.0 or higher and every core service reports running. If the version is older, upgrade Compose first so that every later change is tested on the version you will run in production.

  2. Verify the worker container connects to Redis

    The operator checks that the worker container started and reached the Redis broker. Run docker compose ps worker to confirm it is running, then run docker compose logs --tail 100 worker and look for a clean startup and a successful broker connection with no repeated connection errors. Run docker compose exec redis redis-cli ping and confirm the reply is PONG. Confirm the Redis credentials in your .env file match the Redis service. The step is done when the worker is running, its logs show a stable connection, and Redis answers the ping. Do not scale anything until this passes.

  3. Record a baseline queue depth under normal load

    During a normal working period, the operator records how many tasks wait in the Celery queues that handle dataset indexing and workflow execution. Confirm the queue names in the worker logs or in the source for your Dify version, then read their lengths with docker compose exec redis redis-cli llen followed by the queue name. Take readings at intervals you choose and note what was happening at each one, such as a bulk document upload or a scheduled workflow. Also time one representative knowledge base indexing job. The step is done when you have a table of queue depths, job activity and completion times that you can compare against later.

  4. Enable the dataset queue monitor and email delivery

    The platform engineer sets the variables for the dataset queue monitor and the mail provider in .env, using the names listed in the environment variable reference for your version, and confirms each name against .env.example. Apply the change with docker compose up -d so the api and worker read the new values. Send a test alert by temporarily lowering the monitor threshold, or use the test path the monitor documents if one exists, and confirm the email arrives. Test mail separately from the monitor too, since invitations and password resets use the same provider. The step is done when a test alert reaches the intended inbox and the mail provider logs show an accepted message.

  5. Scale worker containers and re-measure

    The operator runs more worker containers with docker compose up -d --scale worker=N, choosing N from the CPU and memory the host has free after the core services take their share. Before scaling, confirm the worker service has no fixed host port or fixed container name, since either blocks multiple replicas. Repeat the baseline load from the earlier step and compare how quickly the queue drains, the indexing completion time and any new errors. Watch PostgreSQL connection counts and Redis memory while you do this, because more workers add load to both. The step is done when the same load drains faster or with fewer waiting tasks and no new errors or connection exhaustion appear in the logs.

  6. Test a deploy with warm shutdown

    The operator tests what happens to running work during a deploy. Start an indexing job or a long workflow, then run the same stop and start sequence you would use for an upgrade, such as docker compose up -d after pulling new images. Watch docker compose logs -f worker to see whether the worker finishes its current tasks before it exits. Confirm the stop grace period for the worker service in your Compose file, since Docker sends a forced kill after that period. Afterward, check the document status in the knowledge base and the workflow run history. The step is done when the in-flight job either completed or shows as retried, and no index is left partly written.

What happens to in-flight tasks during a deploy

A worker container that is stopped abruptly can leave indexing or workflow tasks half finished, so the goal during a deploy is to let running Celery tasks complete before the container is replaced. Docker sends a stop signal and then a kill after a grace period. Celery treats a warm shutdown as a request to stop taking new work while the tasks already executing finish. The grace period your Compose setup allows (the stop_grace_period value on the worker service, or the docker compose stop timeout) has to be long enough for the largest indexing job you normally run. Confirm both values in your own file and compare them with how long your longest document batch takes in a test environment. The Dify docs do not give a number for this, so the value is yours to set and test.

The risk of a hard stop is concrete. A document can be partly chunked, with some segments written to the vector store and others missing, and the dataset may show a status that does not match its content. Workflow runs that were midway through a node can also end in an unclear state. Recovery is usually a re-index or a retry, which costs model and embedding calls again. To check behavior in the version you run, trigger a large indexing job, issue a docker compose stop worker during processing, and then review the dataset's document status and the worker logs after restart. Repeat the test after any change to the worker's command or stop timeout. Make sure the test is run against the target version, because worker startup and shutdown handling can change between releases.

Treat every deploy as an upgrade with a fixed order. Follow the upgrade guide for the target version on the GitHub Releases page, take a backup before you pull new images, and check .env.example for variables the new version expects. Drain the queue where you can by pausing new dataset uploads and waiting for the monitor to show no active work before you restart workers. Plan the window with the release cadence in mind, since minor releases have arrived roughly monthly. Ask your operations team to record the stop timeout, the backup identifier and the queue depth at the moment of the stop, so a failed deploy can be traced to a specific state.

Security and operational risks in the worker tier

The worker tier sits between the API, Redis, the sandbox and your mail server, so a weakness in any one of them reaches indexing and workflow jobs. The cards below cover the access, secret, network and data exposure points to review before you scale workers or turn on backlog alerts.

Redis exposure and service authentication

Celery uses Redis as the broker that carries job messages between the api and the worker containers. Anyone who can reach that Redis port can read, reorder or inject jobs, so keep it on the internal Compose network only and confirm it requires a password. Check that no port mapping publishes Redis to the host or a load balancer, and review the firewall rules on any host that runs workers.

Token-based authentication between services

Dify 1.16.1 added token-based API authentication between its services, which narrows what a compromised container can call. Confirm that your deployed version includes this change before you assume it applies, and check the release notes for any configuration it requires. Do not expose internal service ports to the network while relying on this control.

Sandbox and outbound request controls

Workers run indexing, tool calls and sandboxed code, and their outbound requests pass through the SSRF proxy and the agent sandbox network isolation. A blocked private address or a proxy timeout can fail a job that looked healthy in the queue. Review the proxy allowlist and timeouts together with worker concurrency so that retries do not pile up behind blocked calls.

Secrets in the environment file

The .env file holds SECRET_KEY, which signs session cookies and JWTs and encrypts OAuth credentials. Changing it after deployment logs out all users, so it must be generated once, stored in your secrets manager and backed up with the rest of the configuration. Restrict file permissions on .env, keep it out of version control and confirm that every worker container reads the same value.

Alert emails carrying operational data

Backlog alerts sent by the dataset queue monitor can include queue names, counts and timing, which tells an outsider how busy your indexing pipeline is. Route alerts to a named distribution list, avoid forwarding to personal mailboxes and confirm the mail provider's retention policy. Treat the alert body as operational data that needs the same handling as your monitoring output.

Worker logs holding document content

Worker logs can record failed indexing jobs, and error messages may include fragments of the documents being processed. Limit who can read container logs, set a retention period that matches your data policy and check whether log shipping sends this content to a third-party service. Ask your Dify team to confirm which log levels are enabled in production.

Questions operators ask before scaling Dify workers

What does it cost to run more Dify workers?

Most of the cost is the extra compute the worker containers consume, plus the database, Redis and vector store capacity that the extra indexing and workflow load draws on. The Dify Docker Compose deployment starts a worker service alongside the api, web and other core services, and the minimum for the whole stack is at least 2 CPU cores and 4 GB of RAM according to the Dify self-hosting docs. Recurring costs grow with how many workers you run, how large your documents are and how often knowledge bases re-index. Ask your team to size workers from measured queue depth and resource use, not from a guess, and to price the host capacity, storage and monitoring as recurring line items.

How long does a Dify worker scaling and queue monitoring build take?

Duration depends on how many hosts run workers, whether Redis and PostgreSQL are external or inside Compose, how mail alerts must route, and whether the team needs a documented warm shutdown procedure for deploys. A single Compose host with one alert recipient is a much smaller job than several hosts with shared Redis, SMTP relay approval and a tested deploy runbook. DeployOpen does not publish timelines; the written scope sets the schedule, so ask for the dependencies and milestones to be listed before work starts.

What does our team need to provide for worker scaling work?

Plan for Docker host access with permission to edit the Compose file and .env, the Redis connection details and the database host, and the SMTP or mail provider settings used for queue alerts. You will also need recent load data: indexing job counts, workflow run volumes, queue backlog history and the resource graphs for the current hosts. Confirm the Dify version you run before changes, because upgrade notes in the Dify releases page can change worker behavior, and keep a backup before any change as the Docker Compose docs recommend.

Can an internal platform team scale Dify workers and set up alerts alone?

Yes, a team with Docker Compose, Redis and mail administration experience can do the core work using the Dify docs and its environment variable reference. The harder parts are judging how many workers the load needs, confirming that a deploy does not cut off in-flight indexing jobs, and making alerts reach an on-call owner. Those tasks need test runs under realistic load, which takes staff time. Decide early whether the team has that capacity and who owns the result after handover.

What goes wrong when Dify workers are scaled without checking the queue?

The usual failures are indexing jobs that stall while workers compete for the same Redis queue, workflow runs that wait longer than users expect, and deploys that stop workers in the middle of a job. Adding containers also raises load on PostgreSQL connections and the vector store, so the bottleneck can move rather than disappear. Watch backlog size, job age, failed task counts and database connection use together before and after each change.

When should we bring in a partner for Dify worker operations?

Bring in a partner when the workload is business-critical, when several environments share Redis or the vector store, or when your team lacks time to run load tests and deploy drills. A partner is also useful when you need a written, fixed-scope change with acceptance checks. DeployOpen plans, implements, documents and supports self-hosted platforms inside your own infrastructure, and most engagements are fixed-scope with scope agreed in writing before work starts. Ongoing monitoring and upgrades are available as retainers.

Does the worker setup require secrets or access to our vector store?

Worker containers need the same SECRET_KEY and connection settings as the api service, so changing them incorrectly can break logins or background tasks. The Dify environment reference says changing SECRET_KEY after deployment logs out all users, so do not rotate it as part of a scaling change. Limit who can read .env, keep Redis reachable only from the Dify network, and confirm which credentials the mail alert path uses before you grant access.

How DeployOpen scopes and supports Dify worker operations

DeployOpen plans and operates Dify worker capacity inside your own infrastructure, starting from the indexing and workflow load your team actually expects. We set up the queue monitoring, alerting and shutdown behavior as part of a written scope, then document and hand them over so your operators can run them.

How we scope

  • Written scope records which worker queues, workloads and deploy paths are in and out of the engagement.
  • We inventory your current Compose or deployment layout, Redis and PostgreSQL placement, and where indexing and workflow runs happen.
  • Scope names the alert recipients, mail delivery dependency and the target environments such as staging and production.

How we build

  • We size worker containers against your indexing and workflow load, then test scaling changes in a non-production copy first.
  • We configure the dataset queue monitor and its email alerts, and verify that a simulated backlog triggers the expected notification.
  • We check warm shutdown behavior during a rolling deploy so in-flight indexing tasks finish or requeue as your team expects.

How we hand over

  • Deliverables include a written runbook covering scaling steps, queue checks, alert thresholds and rollback for worker changes.
  • We walk your operators through the monitor output, the alert emails and the commands used to inspect and drain queues.
  • Documentation records the Dify version tested, configuration keys changed and the verification steps used for each item.

How we support

  • Ongoing support, upgrades and continuous testing are available as retainers, so worker changes can follow each Dify release.
  • Before a minor upgrade, we review release notes and environment variable changes that could affect Celery workers or queues.
  • Ask us to confirm the retainer scope, response expectations and which environments are covered before you sign.

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.