# The negative leap second: the clock bug nobody has rehearsed in production

> All 27 leap seconds added time and still broke Linux and Cloudflare. A deleted second jumps clocks forward instead, and on 15 October 2026 the CGPM votes.

- Source: https://ivankarpinskyi.dev/blog/negative-leap-second
- Published: 2026-10-08
- Type: Changes
- Tags: leap-seconds, linux, ntp, time, nodejs
- Reading time: 7 min

On 15 October 2026 the General Conference on Weights and Measures [votes on Draft Resolution C](https://www.bipm.org/en/cgpm-2026/agenda-day-3), which would stop inserting leap seconds into UTC from 20 May 2027. As of 8 October the vote has not happened. The argument for it comes from software rather than astronomy: every one of the 27 leap seconds so far _added_ a second, several still took down production systems, and the next one may have to _delete_ a second, which no production fleet has ever lived through.

The forecasts for that deletion disagree, and the latest rotation data point away from it. The case for ending leap seconds does not need the forecast to be right. It rests on a modest probability multiplied by a failure mode nobody can rehearse.

## Why UTC keeps getting patched by one second

UTC ticks on atomic clocks. UT1 tracks the actual rotation of the Earth, which wanders. The IERS keeps the two within 0.9 s of each other and, when the gap grows, announces a leap second in [Bulletin C](https://lists.iana.org/hyperkitty/list/tz@iana.org/thread/QXCI2R2IOCR6XHSWBBTYXXE4WT2LEY3R/), issued every January and July. Since 1972 every correction has gone the same way, because the Earth was running slow.

**Leap seconds inserted per decade**

| | Value |
| - | -: |
| 1972–79 | 8 |
| 1980–89 | 6 |
| 1990–99 | 8 |
| 2000–09 | 2 |
| 2010–19 | 3 |
| **2020–26** | 0 |

_Count by effective date of the step, from the IERS UTC-TAI history file. All 27 were positive; the last took effect on 1 January 2017._

The drought is the Earth speeding up. Duncan Agnew's [2024 Nature paper](https://www.nature.com/articles/s41586-024-07170-0) and [the Scripps release on it](https://scripps.ucsd.edu/news/global-warming-influencing-global-timekeeping) put numbers on it: in 1972 a rotational day ran 2.5 ms longer than an atomic day, and by 2023 the excess was down to 80 µs. Push past zero for long enough and UT1 drifts _ahead_ of UTC. The fix for that is a negative leap second: 23:59:58 followed directly by 00:00:00.

## Each positive leap second broke a different assumption

The incidents share a date pattern and nothing else. Each one found a separate piece of code that had never seen a repeated second.

- **31 December 2008 — Linux hard hangs** (\~53 reports on LKML)

  Linas Vepstas [collected the reports](https://lkml.iu.edu/hypermail/linux/kernel/0901.0/00559.html). Warner Losh, in the same thread, already used the phrase "negative leap second" for the opposite case.
- **30 June 2012 — hrtimer CPU storm** (Reddit down 30–40 min, Qantas to manual check-in)

  The kernel set CLOCK\_REALTIME back a second but never called `clock_was_set()`, a call removed in 2007 to dodge a deadlock. Absolute futex timeouts returned instantly and loops spun until reboot.
- **30 June 2015 — Early timers** (up to \~10 ms window, HZ-dependent)

  The kernel applied the leap on the next timer tick rather than at the second edge, so timers in that window fired early. Cisco flagged a critical NX-OS bug.
- **1 January 2017 — Cloudflare RRDNS** (\~0.2% of DNS queries at peak, 6 h 45 min)

  A Go service measured resolver latency as a difference of two `time.Now()` values. Across the repeated second it went negative and `rand.Int63n` panicked.

The 2012 bug is the clearest. John Stultz's [patch analysis](https://lwn.net/Articles/504658) reproduced it on kernels from 2.6.32 to 3.5-rc4 and traced it to commit 746976a301ac in 2.6.22. The airline outage came through Amadeus's Altea system, roughly 48 minutes by The Register's account. Press reports at the time also named Mozilla, Yelp and LinkedIn; none published a postmortem.

Cloudflare's [own write-up](https://blog.cloudflare.com/how-and-why-the-leap-second-affected-cloudflare-dns/) is the canonical one, partly because the fix was one character: `rttMax <= 0` instead of `== 0`. Russ Cox cited it in the [monotonic time design doc](https://github.com/golang/proposal/blob/master/design/12914-monotonic.md), and [Go 1.9](https://go.dev/doc/go1.9) shipped in August 2017 with a monotonic reading inside every `time.Time`. The backward-step bug class got a language-level fix. Its mirror image never had to.

## A deleted second jumps the wall clock forward

The kernel's [`second_overflow()` in ntp.c](https://github.com/torvalds/linux/blob/master/kernel/time/ntp.c) says it plainly: the insert state sets the clock back one second, the delete state sets it ahead. On a deletion CLOCK\_REALTIME jumps +1 s, CLOCK\_MONOTONIC does not move, and Unix time never takes the value for 23:59:59.

That flips which bugs fire, and this is analysis from the code rather than a reported incident. Cloudflare's negative duration cannot happen. In its place, any interval measured on the wall clock across midnight reads a full second too long. A positive number passes every `<= 0` guard ever written. Deadlines computed as `Date.now() + n` expire a second early, so TTLs and leases are cut short. A scheduler that fires on `now == target` has no 23:59:59 to match, and a rate limiter keyed on the wall-clock second loses one window entirely. Log ordering survives: a deletion leaves a gap where an insertion leaves a duplicate.

NTP announces it with leap indicator 2, "last minute has 59 seconds", in RFC 5905. A 2026 operator guide claims LI=2 has never been sent in production, which fits the history but comes from a single weak source.

> **Warning · Never tested holds for fleets, not for the kernel**
>
> Stultz's [leap-a-day.c selftest](https://raw.githubusercontent.com/torvalds/linux/master/tools/testing/selftests/timers/leap-a-day.c) has alternated inserts and deletes for years, and it caught a real STA\_INS/DEL bug in 3.5. Chrony documents its deletion path too. What has never run is a deletion across a fleet of applications. Meta's 2022 line is the accurate one: the impact "has never been tested on a large scale".

The big operators avoid the step entirely by smearing, and smearing a deletion means running clocks _fast_. Google says a negative leap second [would be smeared](https://developers.google.com/time/smear) "by speeding up clocks over the 86,399 SI seconds from noon to noon", roughly 11.6 ppm. CLOCK\_MONOTONIC follows frequency adjustments, so for that day even monotonic durations run about a second fast per 24 hours: harmless for timeouts, visible to anything that measures ppm.

| Time source | Smear window | Shape | Negative case documented? |
| - | - | - | - |
| Google Public NTP | 24 h, noon to noon | linear, \~11.6 ppm | yes, clocks sped up (vendor) |
| Amazon Time Sync, NTP | 24 h, noon to noon | linear | no |
| Amazon Time Sync, [PTP hardware clock](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/set-time.html) | none | steps | no |
| Meta NTP | 17 h from 00:00 UTC | quadratic | no |
| Windows | none, "not UTC-compliant" | steps | no |

Google, AWS and chrony all say the same thing: do not mix smeared and unsmeared sources. Mid-smear the two disagree by up to about 0.5 s, and a stepped source disagrees by the full second at the end. Nothing in the NTP packet tells a client which kind of server it is talking to.

## Nobody agrees the negative second is coming

The headline date, "around 2029", is Agnew's 2024 estimate. His own later paper cut it to a probability, and the most recent rotation data look worse for the forecast.

| Source | Published | Forecast | Method |
| - | - | - | - |
| Agnew, Nature | March 2024 | \~2029; \~2026 without polar ice melt | rotation model, core plus ice melt |
| Malkin, Astronomy Reports | 2024 | not before the early 2030s | rebuttal of Agnew's model |
| BIPM/IERS workshop | March 2025 | \~30% before 2035 | not stated in available sources |
| Agnew, [Metrologia](https://iopscience.iop.org/article/10.1088/1681-7575/ae449f) | February 2026 | \~25% before 2035 | 8,000 Monte Carlo runs of UT1 over 75 years |
| Malkin, [project page](https://www.gaoran.ru/english/as/utc/index.htm) | 8 October 2026 | "rather unlikely at present" | observed day length, 2020–2026 |

**Record-short days**

| | Value, ms | Note |
| - | -: | - |
| 19 July 2020 | 1.46 | |
| 29 June 2022 | 1.59 | |
| **Early July 2024** | 1.66 | |
| 10 July 2025 | 1.37 | |
| July 2026 | 0.65 | forecast |

_Milliseconds shorter than 86,400 s. Daily length-of-day from IERS data as relayed by timeanddate (secondary; the IERS series was unreachable), 2022 from NASA's Space Geodesy Project. 2025 sources range 1.36–1.38. The 2026 bar is a forecast, not a measurement._

The peak is fading. Malkin's page reports yearly-average day length turning positive for the first time since June 2020. If that holds, the vote ends leap seconds just as the case for a negative one weakens. The two are consistent: a 25% chance of an event with zero production history is the kind of risk timekeepers can remove by changing a rule instead of fixing code. Bulletin C 72, published on 6 July 2026, already rules out any leap second at the end of 2026.

## What the vote changes, and what it leaves alone

- **Allowed gap between UT1 and UTC**: 0.9 → 3600 s. Draft C as quoted on Markus Kuhn's Cambridge leap-second page; simple majority needed.
- **TAI−UTC offset if Draft C passes**: 37 s. The step simply stops; the offset freezes where it is today. Pending the 15 October vote.

The [2022 Resolution 4](https://www.bipm.org/en/cgpm-2022/resolution-4) is often summarised as "leap seconds abolished by 2035". It only promised to raise the tolerance by then. Draft C would set the number, an hour, which the CCTF chose for "several centuries" of continuity, and pull the date forward from 2035 to 20 May 2027. Russia voted against in 2022 because GLONASS embeds leap seconds; its 2026 position is not public.

If Draft C passes, the step simply stops. Your existing code does not change, and TAI−UTC stays at 37 s. If it fails, nothing happens before January 2027 at the earliest, because the next possible leap second is 30 June 2027 and Bulletin C 73 has to announce it six months ahead.

## Is there anything to check now?

The useful checks do not depend on the outcome, and they overlap with the general case in [why timestamps lie](/blog/clocks-lie-distributed-systems).

- **Measure durations on a monotonic clock.** In Node, `process.hrtime.bigint()` and `performance.now()`; `Date.now()` reads CLOCK\_REALTIME and would jump +1000 ms on a deletion.
- **In Go, keep the monotonic reading.** `Sub`, `Before` and `After` use it, but `Round`, `Truncate` and `AddDate` strip it.
- **Pick one smear policy per fleet.** Mixing Google Public NTP with an unsmeared pool, or Amazon's NTP with its PTP clock, gives you a one-second disagreement by design.
- **Grep for equality on wall-clock seconds.** A scheduler or rate limiter that waits for an exact second is the code a deletion would skip.

```ts title="src/elapsed.ts"
// Node ≥10.7: hrtime.bigint() ignores clock steps; Date.now() does not.
const start = process.hrtime.bigint();
await doWork();
const elapsedMs = Number(process.hrtime.bigint() - start) / 1e6;
```

If you already do all four, you are unaffected either way. If you do none, a passed Draft C makes that moot from May 2027. A failed one leaves your code facing a deleted second that nobody has ever run it through.

> **Note · Currency**
>
> Written 8 October 2026, before the CGPM vote. Draft Resolution C is scheduled for the 14:15 CEST session on 15 October 2026; check the [BIPM CGPM-28 page](https://www.bipm.org/en/cgpm-2026/agenda-day-3) for the outcome before acting on anything here. The latest IERS Bulletin C (72, 6 July 2026) announces no leap second for December 2026; Bulletin C 73 is due January 2027.

## Sources

- [votes on Draft Resolution C](https://www.bipm.org/en/cgpm-2026/agenda-day-3), bipm.org
- [Bulletin C](https://lists.iana.org/hyperkitty/list/tz@iana.org/thread/QXCI2R2IOCR6XHSWBBTYXXE4WT2LEY3R/), lists.iana.org
- [2024 Nature paper](https://www.nature.com/articles/s41586-024-07170-0), nature.com
- [the Scripps release on it](https://scripps.ucsd.edu/news/global-warming-influencing-global-timekeeping), scripps.ucsd.edu
- [collected the reports](https://lkml.iu.edu/hypermail/linux/kernel/0901.0/00559.html), lkml.iu.edu
- [patch analysis](https://lwn.net/Articles/504658), lwn.net
- [own write-up](https://blog.cloudflare.com/how-and-why-the-leap-second-affected-cloudflare-dns/), blog.cloudflare.com
- [monotonic time design doc](https://github.com/golang/proposal/blob/master/design/12914-monotonic.md), github.com
- [Go 1.9](https://go.dev/doc/go1.9), go.dev
- [second_overflow() in ntp.c](https://github.com/torvalds/linux/blob/master/kernel/time/ntp.c), github.com
- [leap-a-day.c selftest](https://raw.githubusercontent.com/torvalds/linux/master/tools/testing/selftests/timers/leap-a-day.c), raw.githubusercontent.com
- [would be smeared](https://developers.google.com/time/smear), developers.google.com
- [PTP hardware clock](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/set-time.html), docs.aws.amazon.com
- [Metrologia](https://iopscience.iop.org/article/10.1088/1681-7575/ae449f), iopscience.iop.org
- [project page](https://www.gaoran.ru/english/as/utc/index.htm), gaoran.ru
- [2022 Resolution 4](https://www.bipm.org/en/cgpm-2022/resolution-4), bipm.org
