Huny's Dev Blog
huny.dev

Use Python monotonic_ns for Timeouts That Survive Wall Clock Changes

Use Python monotonic_ns to enforce a total timeout budget. Reproduce wall clock adjustments and understand how retries and system suspend affect deadline calculations.

Hun Jang
Hun Jang Nov 14, 2026

If requests time out too soon or wait too long after a system clock change, check whether your Python service uses time.time() for timeout calculations. To limit how much time an operation spends running, calculate one deadline at the start with time.monotonic_ns() and recompute the remaining time at each step. The example checks whether a request keeps the same time budget when the wall clock moves forward or backward.

Two clocks side by side, one showing a time adjustment and the other advancing steadily

Why the wall clock changes the remaining time

time.time() returns seconds corresponding to calendar time. When the operating system adjusts its clock, the difference between successive calls can reflect both the actual wait and the adjustment. With a five-second timeout, for example, shifting the wall clock 30 seconds backward after two seconds of elapsed time produces a remaining time of 33 seconds. Moving it 30 seconds forward makes the deadline appear to have expired.

time.monotonic_ns() returns an integer count of nanoseconds from a clock that cannot go backward. Its reference point is undefined, so use the difference between readings from the same clock. Use wall time to record dates and expiration timestamps, and a monotonic clock to calculate the remaining time for work in progress. Python time documentation

Calculate the overall deadline once

Set deadline = monotonic_ns() + budget_ns. Before each attempt, recompute remaining_ns(deadline) and skip the attempt if it is zero. For an API that accepts a timeout in seconds, divide the positive remainder by 1_000_000_000. If you wait between retries, keep the wait within the remaining budget and check it again afterward. Giving every attempt the full timeout can let the operation exceed its intended total limit.

Save the code as monotonic_deadline.py and run python3 monotonic_deadline.py. It simulates adjustments with a test clock.

Verify forward and backward adjustments

The example ran on Linux with Python 3.12.14 on November 14, 2026. Both 30-second adjustments left three seconds on the monotonic clock. The test also checked that the remainder becomes zero after additional elapsed time and that a deadline set to the current value from the actual monotonic_ns() clock returns zero.

Keep deadlines within their clock and account for suspend

Use a monotonic deadline with the same clock that produced it. When sending timing information to another host, use a protocol-defined remaining duration or absolute expiration timestamp. When the receiver assigns a new time budget, decide how the protocol accounts for time in transit and differences between host clocks.

On Linux, CLOCK_MONOTONIC is unaffected by discontinuous wall clock changes, but it can be affected by gradual clock adjustments and excludes time spent suspended. Linux tasks that need to count suspend time can use CLOCK_BOOTTIME. Check the clock used by the current Python process with time.get_clock_info("monotonic"). This example simulates the effects of clock adjustments. System suspend and timeout behavior in specific network APIs were outside the test scope. Linux clock_gettime(2) · Python time documentation

한국어 버전 · Python 타임아웃이 시스템 시각 변경에 흔들릴 때 monotonic_ns 쓰기Python 타임아웃이 시스템 시각 변경에 흔들릴 때 monotonic_ns 쓰기

추천 글