Systemd unit restarts in a tight loop and gives up with 'start request repeated too quickly
Systemd unit restarts in a tight loop and gives up with "start request repeated too quickly"
At 03:12 the pager fires: a payment worker is down. systemctl status shows failed, and the journal is full of start/stop pairs. Systemd has stopped trying because the unit hit its start limit, and the last line reads start request repeated too quickly. The cost is not just one crashed process. The loop has burned CPU, filled the journal, and left queued jobs unprocessed.
What systemd start request repeated too quickly actually means
This message is a rate-limit verdict, not the underlying crash reason. Systemd counts unit start attempts inside a time window. When attempts exceed StartLimitBurst within StartLimitIntervalSec, systemd marks the unit failed and stops restarting it until you clear the failed state. See the start-limit behavior in the systemd documentation [link needed].
The exact phrase systemd start request repeated too quickly usually means: the service crashes fast, Restart= keeps bringing it back, and the limiter finally wins. Fixing the limiter without finding the crash is temporary.
Diagnose the loop before changing limits
Run this in order. Do not skip step 3.
1. Capture the current state and limits:
```bash
systemctl status my.service --no-pager
systemctl show my.service -p NRestarts -p Restart -p RestartSec \
-p StartLimitBurst -p StartLimitIntervalUSec
systemctl cat my.service
```
2. Read the last cycles for exit codes and repeated errors:
```bash
journalctl -u my.service -b --no-pager -n 100
```
Look for status=, code=exited, permission errors, missing paths, port conflicts, and dependency failures.
3. Reproduce the command manually with the same user and environment shown by systemctl cat. For example:
```bash
sudo -u appuser env $(systemctl show my.service -p Environment --value) \
/usr/local/bin/my-worker --config /etc/my-worker.conf
```
4. Fix the root cause: missing directory, wrong ownership, bad config, occupied port, unavailable mount, or failed dependency.
5. Clear the failed state and start once:
```bash
systemctl reset-failed my.service
systemctl start my.service
systemctl status my.service --no-pager
```
Stabilize first, then tune the start limiter
If the crash is genuinely transient, such as a dependency race at boot, slow network mount, or briefly unavailable database, adjust RestartSec first. A few seconds between attempts is usually better than instant restarts. Then, only if needed, raise the limit in the [Unit] section, not [Service]:
[Unit]
StartLimitIntervalSec=60s
StartLimitBurst=10
[Service]
Restart=on-failure
RestartSec=5s
Apply and retry:
systemctl daemon-reload
systemctl reset-failed my.service
systemctl start my.service
This allows up to 10 starts in 60 seconds, spaced by 5 seconds. If the service still ends with systemd start request repeated too quickly, you delayed the failure but did not fix it. Check systemctl show rather than assuming defaults [link needed].
When NOT to do this
Do not raise StartLimitBurst when the process exits immediately for a deterministic reason: a typo in ExecStart, missing binary, bad config, wrong permissions, or a port already in use. More retries just fill logs and delay the obvious failed state.
Do not tune limits first when the host is out of memory, file descriptors, or disk. Restarting faster can add load. Also avoid setting StartLimitIntervalSec=0 everywhere; infinite retries can hide a permanent outage. For Type=oneshot units, repeated failed starts usually point to dependencies or command errors, not a need for a larger burst.
Checklist
- [ ] Confirmed
NRestarts,Restart,RestartSec, and start-limit values. - [ ] Read journal exit codes and the last 100 lines.
- [ ] Reproduced the command as the service user.
- [ ] Fixed the root cause before changing limits.
- [ ] If transient, set a sane
RestartSecand[Unit]limit. - [ ] Ran
daemon-reload,reset-failed, thenstart. - [ ] Watched one full start-limit interval without another loop.