systemd: Start request repeated too quickly — StartLimitBurst in [Service] still works, StartLimitIntervalSec does not

Linux medium systemdservicerestartcentos7debian
lab-flap.service: Start request repeated too quickly.
lab-flap.service: Failed with result 'exit-code'.

What you see

A service restarts a few times and then stops for good. systemctl status reports:

lab-flap.service: Start request repeated too quickly.
lab-flap.service: Failed with result 'exit-code'.
Active: failed (Result: exit-code)

The unit has a StartLimit setting, the value in the file is not the value the system used, and every tutorial you find says the opposite of what this page measured.

Why it happens

StartLimitBurst and StartLimitInterval define a sliding window: if the unit is started Burst times within Interval, systemd stops trying. The defaults are 5 starts in 10 seconds, and they apply whether or not you write anything.

What changed in systemd 230 (2016) is narrower than the usual summary. The keys were not moved from [Service] to [Unit] wholesale. Instead:

  • [Unit] started to be read for these keys (before 230 it was not read at all)
  • StartLimitInterval was renamed to StartLimitIntervalSec
  • [Service] kept accepting StartLimitBurst and the old name StartLimitInterval
  • only the new name StartLimitIntervalSec is refused outside [Unit]

So the modern spelling in [Service] is the one combination that breaks — and it breaks quietly enough that nobody notices.

What each section actually accepts

Measured on both systems, same unit, one variable changed per run:

Written whereKey nameCentOS 7 · systemd 219Debian 13 · systemd 257
[Unit]StartLimitBurstignored (stays 5)applied
[Unit]StartLimitIntervalignored (stays 10s)applied
[Unit]StartLimitIntervalSeckey does not existapplied
[Service]StartLimitBurstappliedapplied
[Service]StartLimitInterval (old name)appliedapplied, no warning
[Service]StartLimitIntervalSec (new name)key does not existrefused, falls back to 10s
drop-in[Unit] StartLimitBurstignoredapplied
Which StartLimit combination works on systemd 219 versus 257Three combinations compared. Unit section with the new key name only works from systemd 230 onward. Service section with the old key names works on both. Service section with the new key name is refused on systemd 230 and later, and the window silently falls back to the default 10 seconds.Start request repeated too quicklysystemd gave up restarting the unit — the start limit was hit[Unit]StartLimitIntervalSec=60StartLimitBurst=3219 — ignored, still 5 starts / 10s257 — applied: 3 starts / 1minmodern-only units[Service]StartLimitBurst=3StartLimitInterval=60219 — applied: 3 starts / 60s257 — applied: 3 starts / 1minportable: RHEL/CentOS 7 through Debian 13[Service]StartLimitIntervalSec=60StartLimitBurst=3219 — key does not exist257 — Unknown key, window stays 10sburst honoured, interval silently droppedIf the unit has to run on RHEL or CentOS 7 as well, use the middle row.Never put StartLimitIntervalSec in [Service]: the burst applies, the window does not, and the result looks correct at RestartSec=1.
The three combinations, measured. The middle row is the only one that behaves the same on systemd 219 and 257.

The nine runs on systemd 257

Debian 13, systemd 257.13-1~deb13u1, kernel 6.12.111+deb13-amd64. Unit: ExecStart=/bin/false, Restart=always, RestartSec=1. Effective values come from systemctl show.

RunWrittenEffective burstEffective windowRestartsEnd stateanalyze verify
Anothing510s5failedclean
B[Service] burst=3, IntervalSec=60310s3failedUnknown key line 11
C[Unit] burst=3, IntervalSec=6031min3failedclean
D[Unit] 3/60s + drop-in burst=881min8failedclean
E[Unit] IntervalSec=05014 in 18sstill restartingclean
F[Service] IntervalSec=0510s5failedUnknown key line 10
G[Service] burst=3, Interval=60 (old name)31min3failedclean
H[Unit] IntervalSec=60, [Service] burst=331min3failedclean
Inothing, RestartSec=6510s7still restartingclean

Run B is the one that matters. The burst came from your file, the window did not:

/etc/systemd/system/lab-flap.service:11: Unknown key 'StartLimitIntervalSec' in section [Service], ignoring.

Run G is the other one that matters. Change nothing but the key name and the window is accepted with no warning at all.

The same nine runs on systemd 219

CentOS 7, systemd 219, kernel 3.10.0-1127.el7.x86_64. Identical unit, identical sequence.

RunWrittenEffective burstEffective windowBehaviour
Anothing510sstopped after 5
B[Service] burst=3, Interval=60360sstopped after 3
C[Unit] burst=3, Interval=60510s[Unit] not read at all
D[Unit] 3/60s + drop-in burst=8510sdrop-in ignored
E[Unit] Interval=0510sstill limited
F[Service] Interval=05015 restarts in 18s, unlimited
G[Service] burst=3, Interval=60360ssame as B
H[Unit] Interval=60, [Service] burst=3310sonly the [Service] half applied
Inothing, RestartSec=6510s8 attempts, never limited

On 219 the rule is simple: [Unit] is not read, [Service] is. Anything you put in [Unit] — including a drop-in — is silently discarded.

The version differences that break scripts

systemd 219systemd 257
Property nameStartLimitInterval (microseconds, integer)StartLimitIntervalUSec (10s, 1min)
Restart counterno NRestarts propertyNRestarts
Result valuestart-limitexit-code
Log wordingstart request repeated too quickly for lab-flap.servicelab-flap.service: Start request repeated too quickly.
journalctl -o short-unixunsupportedsupported

Monitoring scripts that query -p StartLimitIntervalUSec get an empty value on RHEL 7 and CentOS 7. Scripts that grep for start-limit-hit find nothing on either version.

Fix

1. Portable unit — [Service] with the old key names. Verified on both 219 and 257:

[Service]
StartLimitBurst=3
StartLimitInterval=60

2. Modern-only unit — [Unit] with the current key names:

[Unit]
StartLimitIntervalSec=60
StartLimitBurst=3

3. Drop-ins. Write the same section the system actually reads. On a fleet that still has 7-series hosts, that means [Service]:

# /etc/systemd/system/myapp.service.d/limits.conf
[Service]
StartLimitBurst=10
StartLimitInterval=120

4. To disable rate limiting entirely, StartLimitIntervalSec=0 must be in [Unit] on systemd 230 and later, and StartLimitInterval=0 must be in [Service] on 219. There is no single spelling that disables it on both.

5. Before blaming the limit, check RestartSec. With RestartSec=1 the measured gap between starts is 1.24–1.26 seconds, not 1.00 — systemd spends about 250 ms per cycle. With RestartSec=6 the gap is 6.25 seconds. Five starts need four gaps, so the default 5-in-10s limit stops triggering at roughly RestartSec=2.25 and above: the window fills with at most two starts and the unit restarts forever (run I: 7 restarts, still activating).

Verify

systemctl show myapp.service -p StartLimitBurst -p StartLimitIntervalUSec
systemd-analyze verify /etc/systemd/system/myapp.service

The first command prints what systemd will actually use, not what your file says. The second prints the Unknown key warning if the name is wrong for that section. Both are cheap; the second one is the only place the mistake shows up before it bites.

What failed

Four things in this lab did not match what I expected. The first two are the reason this page exists.

ExpectationWhat actually happenedWhy
[Service] is not read for StartLimit* since systemd 230StartLimitBurst in [Service] applied on 257 (3 restarts)the keys were added to [Unit], not removed from [Service]; only the renamed StartLimitIntervalSec is refused there
hitting the limit sets Result=start-limit-hit257 reports Result=exit-code; 219 reports Result=start-limitneither version uses that string; grepping for it is a dead end
a wrong section produces no warning at allUnknown key 'StartLimitIntervalSec' in section [Service], ignoring. appears in the journal and in systemd-analyze verifythe warning exists, but only at daemon-reload time — nobody watches for it
centring an 18-second observation on RestartSec=1 is enough to see the limitrun I never hit itthe limit is a sliding window, and RestartSec=6 moves every start out of the previous window

One methodology note, because it cost a full re-run: the first version of the harness deleted the drop-in directory after creating it, so run D reported the [Unit] value and looked like a working result. Re-running with the harness fixed produced 8 restarts instead of 3. A plausible number was the symptom, not the proof.