
Force an explicit sync:
When Mutagen is enabled, DDEV:
Copilot was used to create an initial draft for this blog, and for subsequent reviews.
The benefits far outweigh the caveats for most projects, especially with the new diagnostic tools that identify and help resolve common issues automatically.
ddev config --performance-mode=none && ddev restart
Current file: vendor/bin/large-binary (306 MB/5.2 GB)
Current file: vendor/bin/large-binary (687 MB/5.2 GB)
Current file: vendor/bin/large-binary (1.1 GB/5.2 GB)
Frontend build tools create massive node_modules directories that slow Mutagen sync significantly. Solution: Add node_modules to upload_dirs:
Mostly for PHP
If you’re here because you just need to debug a Mutagen problem, this will probably help:
Webserving Performance Improvement
ddev mutagen reset # Start from scratch
ddev start
If your project has non-standard locations, override defaults by setting upload_dirs in .ddev/config.yaml.
Mutagen is an asynchronous file synchronization tool that decouples in-container reads and writes from reads and writes on the host machine. Each filesystem enjoys near-native speed because neither is stuck waiting on the other.
- Mounts a Docker volume onto
/var/wwwinside the web container - A Linux Mutagen daemon is installed inside the web container
- A host-side Mutagen daemon is started by DDEV
- The two daemons keep each other up-to-date with changes on either side
Lifecycle
ddev start: Starts the Mutagen daemon on the host if not running, creates or resumes sync sessionddev stop: Flushes sync session to ensure consistency, then pauses itddev composer: Triggers synchronous flush after completion to sync massive filesystem changesddev mutagen reset: Removes the Docker volume and the sync session will then be recreated from scratch (from the host-side contents) onddev start.
Upload Directories
The first-time Mutagen sync takes 5-60 seconds depending on project size. A Magento 2 site with sample data might take 48 seconds initially, 12 seconds on subsequent starts. If sync takes longer than a minute, you’re likely syncing large files or directories unnecessarily.
- Drupal:
sites/default/files - WordPress:
wp-content/uploads - TYPO3:
fileadmin,uploads
Use --all flag to analyze all Mutagen volumes system-wide:
Mutagen increases disk usage because project code exists both on your computer and inside a Docker volume. The upload_dirs directories are excluded to mitigate this.
Initial Sync Time
ddev mutagen reset
ddev restart
ddev mutagen sync
ddev mutagen logs
# Backup customizations first
mv .ddev/mutagen/mutagen.yml .ddev/mutagen/mutagen.yml.bak
ddev restart
ddev mutagen monitor
services:
web:
volumes:
- "../web/themes/custom/mytheme/node_modules:/var/www/html/web/themes/custom/mytheme/node_modules"
Watch for volumes larger than 5GB (warning) or 10GB (critical). Use ddev utility mutagen-diagnose --all to check all projects.
- Do Git operations on the host, not in the container
- Use
ddev composerfor most composer operations - Run
ddev mutagen syncafter major Git branch changes - Run
ddev mutagen syncafter manual Composer operations done inside the container
Disk Space Considerations
DDEV now includes a diagnostic tool that automatically checks for common issues:
Mutagen has been a part of DDEV for years, providing dramatic performance improvements for macOS and traditional Windows users. It’s enabled by default on these platforms, but understanding how it works, what can go wrong, and how to debug issues is key to getting the most out of DDEV.
The New ddev utility mutagen-diagnose Command
ddev mutagen status
For more information, see the DDEV Performance Documentation and the Mutagen documentation.
- Volume sizes: Warns if >5GB, critical if >10GB
- Upload directories configuration: Checks if properly configured for your CMS
- Sync session status: Reports problems with the sync session
- Large directories: Identifies
node_modulesand other large directories being synced - Ignore patterns: Validates Mutagen exclusion configuration
Best practices:
Disable per-project:
while true; do ddev mutagen st -l | grep "^Current"; sleep 1; done
#!/usr/bin/env bash
ddev mutagen sync || true
ddev utility mutagen-diagnose
This blog is based on the Mutagen Fundamentals and Troubleshooting Contributor Training held on January 22, 2026.
Monitoring Sync Activity
ddev utility mutagen-diagnose
git pull, deleting files) while DDEV is stopped, Mutagen has no awareness of these changes. When you start again, it may restore old files from the volume.
Manual Sync Control
Disable Mutagen if:
The primary target of Mutagen syncing is PHP files. These were the fundamental problem with Docker as the number of files in a Docker-hosted PHP website grew into the Composer generation with tens of thousands of files, so php-fpm had to open so very many of them all at once. Now with DDEV on macOS using Mutagen, php-fpm is opening files that are just on its local Linux filesystem, not opening ten thousand files that all have to be verified on the host.
ddev utility mutagen-diagnose
ddev utility mutagen-diagnose --all
DDEV_DEBUG=true ddev start
ignore:
paths:
- "/web/themes/custom/mytheme/node_modules"
- "/vendor/large-package"
upload_dirs:
- sites/default/files # CMS uploads
- ../node_modules # Build dependencies
- ../vendor/bin # Large binaries
ddev config global --performance-mode=none
Traditional Docker bind-mounts check every file access against the file on the host. On macOS and Windows, Docker’s implementation of these checks is not performant. Mutagen solves this by maintaining a cached copy of your project files in a Docker volume, syncing changes between host and container asynchronously.
Mutagen supports filesystem notifications (inotify/fsnotify), so file-watchers on both the host and inside the container are notified when changes occur. This is a significant advantage for development tools that would otherwise need to poll for changes.
Solution: Run ddev mutagen reset before restarting if you’ve made significant changes while stopped. That removes the volume so everything comes first from the host side in a fresh sync.
Most people don’t have to change this anyway; macOS and traditional Windows default to performance_mode: mutagen and Linux/WSL default to performance_mode: none.
Add .git/hooks/post-checkout and make it executable:
Access Mutagen directly:
Git Hooks for Automatic Sync
See the slides for the training video.
upload_dirs: #upload_dirs entries are relative to docroot
- sites/default/files # Keep existing CMS defaults
- ../node_modules # Exclude from Mutagen
ddev mutagen status -l
Troubleshooting Steps
-
DDEV automatically excludes user-generated files in
upload_dirsfrom Mutagen syncing, using bind-mounts instead. For most CMS types, this is configured automatically, for example:- You’re on Linux or WSL2 (already has native performance)
- Filesystem consistency is more critical than webserving performance
- You’re troubleshooting other DDEV issues
Mutagen has delighted many developers with its web-serving performance. One dev said “the first time I tried it I cried.”
⚠ 3 node_modules directories exist but are not excluded from sync (can cause slow sync)
→ Add to .ddev/config.yaml:
upload_dirs:
- sites/default/files
- web/themes/custom/mytheme/node_modules
- web/themes/contrib/bootstrap/node_modules
- app/node_modules
→ Then run: ddev restartDebugging Long Startup Times
ddev utility mutagen sync list
ddev utility mutagen sync monitor <projectname>- Use
ddev utility mutagen-diagnoseas your first debugging step - Configure
upload_dirsto exclude large directories likenode_modulesor heavy user-generated files directories - Run
ddev mutagen resetafter file changes when DDEV is stopped - Do Git operations on the host, not in the container
- Monitor sync activity with
ddev mutagen monitorwhen troubleshooting
ddev mutagen reset && ddev config --performance-mode=none && ddev restartWe do note that
upload_dirsis not an adequate description for this behavior. It was originally intended for user-generated files, but now is used for heavy directories likenode_modules, etc.
ddev utility mutagen daemon stop
ddev utility mutagen daemon start
Excluding Directories from Sync
Recommended approach: Use upload_dirs in .ddev/config.yaml:





