Fix Matrix Synapse “Too Many Open Files” on systemd

Matrix Synapse may start normally and then stop accepting connections, log “Too many open files,” or appear stuck under load. On a systemd installation, the first thing to check is the file-descriptor limit inherited by the running Synapse process. Changing a shell’s ulimit or editing a PAM limits file usually does not change the limit for a service that systemd starts.

The steps below apply to a Linux host where Synapse runs as a systemd service. The unit may be named matrix-synapse.service, matrix-synapse@.service, or something package-specific. Confirm the real unit before copying commands. If Synapse runs in Docker, Kubernetes, or another container, see the separate section below.

What does “Too many open files” mean?

Linux gives each process a limit on open file descriptors. A descriptor can refer to a file, socket, pipe, or other resource; network connections therefore consume descriptors too. When a process reaches its soft limit, an attempt to open or accept another descriptor can fail with EMFILE. Linux also has a separate system-wide file table limit: exhaustion there can produce ENFILE. Raising one Synapse service’s limit will not fix a system-wide shortage.

Synapse’s official administration FAQ says that high connection and federation activity can use many file handles and that exhaustion can make the server stop accepting new TCP connections. Its guidance mentions raising the limit to at least 4,096 in the context of older defaults such as 1,024 or 256. Treat that as a troubleshooting floor for the situation described, not a universal capacity recommendation for every homeserver. Start by checking the effective limit and actual usage.

Linux’s getrlimit and prlimit documentation describes the per-process soft and hard limits. Synapse also has a soft_file_limit setting; the Synapse configuration reference documents a default of zero, which tells Synapse to set its soft limit to the hard limit it can use.

1. Confirm the unit and diagnose the failure

Find the actual service name first. On many package installations it is matrix-synapse.service, but do not assume that name if your installation uses a custom unit or workers.

systemctl list-units --type=service --all | grep -i synapse
systemctl status matrix-synapse.service --no-pager
journalctl -u matrix-synapse.service --since "30 minutes ago" --no-pager

Look for the exact error, the time it began, and whether it appears during a traffic spike, federation activity, or a restart. Next, inspect the limit systemd currently reports:

systemctl show matrix-synapse.service -p LimitNOFILE -p MainPID

LimitNOFILE shows the service manager’s configured limit; it is not a count of descriptors currently open. A shell command such as ulimit -n only reports the current shell’s limit and is not proof of the service’s limit.

2. Raise the systemd service limit with a drop-in

Use a systemd drop-in so package updates do not require editing the vendor unit file. The following value is an example, not a guaranteed ideal for every server. Choose a limit with room above observed peak usage, and check application and dependency compatibility before setting an unusually high value.

sudo systemctl edit matrix-synapse.service

Add this under the editor’s new drop-in:

[Service]
LimitNOFILE=65536

Save and exit, then reload systemd and restart Synapse during an appropriate maintenance window:

sudo systemctl daemon-reload
sudo systemctl restart matrix-synapse.service
systemctl show matrix-synapse.service -p LimitNOFILE

A single LimitNOFILE value sets both the soft and hard limit for the service in systemd. The systemd manual also allows a soft:hard pair. The soft limit cannot exceed the hard limit. Before choosing a very high value, review the systemd.exec documentation, which notes compatibility concerns for programs using the old select(2) interface with descriptors above 1,023. Do not assume every library or plugin in your deployment supports any arbitrary limit.

3. Check Synapse’s own setting and worker services

If your Synapse configuration explicitly sets soft_file_limit to a low number, the application setting may keep the soft limit below the systemd ceiling. Search the active configuration files and included configuration for that key. Either remove an unnecessary override or set it deliberately; the documented default of zero asks Synapse to raise its soft limit to the available hard limit.

For a multi-process deployment, each worker is a separate process and may be started by a separate unit or template instance. Raising the main service’s limit does not automatically prove that every worker has the intended limit. Inspect the actual worker unit names with systemctl list-units, then apply and verify the appropriate drop-in for each service that needs it.

Likewise, settings in /etc/security/limits.conf and a login shell’s ulimit generally do not govern a system service launched directly by systemd. For this setup, change the unit’s resource limit and verify it on the process that systemd actually started.

4. If Synapse runs in a container

A host-level systemd override for a different service does not automatically change a container’s file-descriptor limit. Configure the container runtime or orchestration layer. For Docker Compose, the service definition supports per-container ulimits; an example is:

services:
  synapse:
    ulimits:
      nofile:
        soft: 65536
        hard: 65536

The number is illustrative; size it from usage and the host’s limits. Docker’s Compose service reference documents the ulimits setting. As of Docker Engine 29, Docker’s release notes describe a change in the default nofile limit associated with containerd 2.1.5: containers may receive 1,024 rather than the previous 1,048,576 default. If the issue appeared after an Engine upgrade, check the effective container limit and explicitly set the needed ulimit in the deployment configuration. See the Docker Engine 29 release notes and docker run reference.

5. Verify the limit on the running Synapse process

After restart, check the process-level limit, not only systemd’s configuration. Obtain the main PID and inspect its kernel-reported limits:

PID=$(systemctl show --property=MainPID --value matrix-synapse.service)
grep "Max open files" "/proc/$PID/limits"
find "/proc/$PID/fd" -mindepth 1 -maxdepth 1 | wc -l

If the main PID is zero or belongs to a wrapper rather than Synapse, identify the Synapse process in the service’s cgroup and inspect that PID instead. The descriptor count is a snapshot; repeat it during representative load. Confirm that “Max open files” reflects your intended soft and hard limits, the count stays comfortably below the soft limit, and the journal no longer reports the error.

If the count keeps rising until it reaches the new ceiling, the limit may only be postponing the failure. The Synapse FAQ notes that stuck or slow requests can be relevant when investigating file-handle exhaustion. Review surrounding logs and request processing, compare descriptor counts over time, and investigate a possible leak or unexpectedly persistent connections rather than continuing to raise the cap blindly.

When raising the per-service limit is not enough

If logs report a system-wide file-table exhaustion error such as ENFILE, inspect host-wide usage and other services; a per-service LimitNOFILE change will not increase the kernel’s system-wide capacity. Avoid changing global kernel limits without confirming the error and understanding host-wide impact. If the service’s reported limit remains low after a drop-in, run systemctl cat matrix-synapse.service to confirm the drop-in is loaded, verify the unit name, reload systemd, and restart the correct unit.

Quick self-check

  • Did you identify the exact Synapse unit or container that logs the error?
  • Does systemctl show report the intended limit for that unit?
  • Does /proc/<Synapse-PID>/limits show the intended soft and hard limits after restart?
  • Is the descriptor count below the soft limit under normal peak load?
  • Are worker units and container settings checked separately where applicable?
  • Did the error stop, or is usage continuing to grow toward the new ceiling?

If all process-level checks pass and the error has stopped during representative traffic, the systemd limit change is working. If descriptors continue to accumulate or the system reports a global shortage, keep investigating the source rather than treating a larger limit as the complete fix.

Sources

Leave a Comment

7 Best WSUS Tools for Update Management and Troubleshooting

7 Best WSUS Tools for Update Management and Troubleshooting

Compare seven tools that support or complement WSUS, from Microsoft’s native console and diagnostics to third-party patch publishing and remote deployment.

Best Windows System Monitoring Tools: 6 Picks for Server Visibility

Best Windows System Monitoring Tools: 6 Picks for Server Visibility

Compare six Windows system monitoring tools for server health, application visibility, and alerting, with current notes on deployment and licensing.

7 Wake-on-LAN Tools: What’s Still Available From the 2021 List

7 Wake-on-LAN Tools: What’s Still Available From the 2021 List

Compare seven Wake-on-LAN tools by features and availability, including free utilities, network-admin suites, and 2021 picks that have since been retired.

9 Best Ping Tools for Testing Latency and Scanning a Network

9 Best Ping Tools for Testing Latency and Scanning a Network

Compare nine ping tools for quick reachability checks, subnet discovery, TCP tests, and latency monitoring, with guidance on which one fits your network task.

Best TFTP Servers for Windows, Linux, and macOS

Best TFTP Servers for Windows, Linux, and macOS

Compare the best TFTP servers for Windows, Linux, and macOS, including SolarWinds, Tftpd64, tftpd-hpa, atftpd, haneWIN, and dnsmasq.

5 Best Microsoft Access Alternatives for Desktop and Web Databases

5 Best Microsoft Access Alternatives for Desktop and Web Databases

Compare five Microsoft Access alternatives for desktop, SQLite, no-code, and browser-based database work, with strengths, limits, and best-fit use cases.

Open-Source vs. Closed-Source Monitoring Tools Compared

Open-Source vs. Closed-Source Monitoring Tools Compared

Compare open-source and closed-source monitoring tools by cost, support, customization, security, and current options including Zabbix, Nagios, PRTG, and more.

Ingress vs. Egress: What’s the Difference in Networking?

Ingress vs. Egress: What’s the Difference in Networking?

Understand how ingress and egress describe incoming and outgoing traffic, why direction depends on the network boundary, and how to monitor bandwidth and spot risky data transfers.

6 Best Free Syslog Servers to Try for Centralized Logging

6 Best Free Syslog Servers to Try for Centralized Logging

Compare six free syslog servers and collectors for Windows and Linux, including GUI tools, open-source options, search, alerting, and secure transport.

What Is IIS? Microsoft’s Windows Web Server and Alternatives

What Is IIS? Microsoft’s Windows Web Server and Alternatives

See what Microsoft IIS does, how its request pipeline and application pools work, and when Apache, NGINX, or Caddy may fit your web server needs better.