cd /news/artificial-intelligence/don-t-review-ai-code-review-its-cloc… Β· home β€Ί topics β€Ί artificial-intelligence β€Ί article
[ARTICLE Β· art-102466] src=sourcefeed.dev β†— pub= topic=artificial-intelligence verified=true sentiment=Β· neutral

Don't Review AI Code. Review Its Clock.

A Dev.to post by Taylor Wang argues that reviewing AI-written rate limiters should focus on whether the code allows injecting a fake clock, not on the bucket math, because injectable time turns generated code into a verifiable table. The post notes that Go 1.25 stabilized testing/synctest and .NET 8 shipped time abstraction, showing platform teams already prioritize this seam. Rachel Goldstein's article frames this as the difference between code you can verify and code you have to trust, recommending prompts that require a clock/now parameter and a mechanical review rule to reject direct system time calls.

read6 min views3 publishedAug 19, 2026
Don't Review AI Code. Review Its Clock.
Image: Sourcefeed (auto-discovered)

AIArticle

Injectable time turns an LLM-written rate limiter from trust-me code into a table you can verify in microseconds.

Rachel Goldstein

A rate limiter is a nasty thing to review, because reading it tells you almost nothing. The code compiles, the variable names are plausible, the refill math looks right at a glance β€” and every real defect lives at a boundary you can't see until a client crosses it at 2 a.m. and your support queue fills with 429 complaints. Now multiply that by the way this code increasingly gets written: you ask an LLM for a token bucket, it hands you forty confident lines, and you're the only human who will ever look at them.

A recent Dev.to post by Taylor Wang made a small argument I think deserves a bigger frame: when you review an AI-written rate limiter, the part worth scrutinizing isn't the bucket math. It's whether the code lets you inject a fake clock. That's not a testing nicety. It's the difference between code you can verify and code you have to trust β€” and with generated code, trust is exactly the thing you don't have.

The seam is the review #

Most generated rate limiters read the wall clock directly β€” time.time()

, Date.now()

, DateTime.UtcNow

β€” because that's what the bulk of tutorial code on the internet does, and models reproduce the majority pattern. The moment the limiter reaches for the system clock itself, its behavior becomes a function of when you run it. Your test either sleeps through real seconds (slow, flaky, and still imprecise) or it doesn't test the boundaries at all.

Flip the dependency and everything changes. Pass time in β€” a clock object, or just an explicit now

argument β€” and the limiter collapses into a pure function: given this configuration, this key, and this sequence of timestamps, which requests pass? That's a table you can write down before you read a single line of the generated implementation. Which is the right order of operations: start from the failures you want to catch, not from the model's confident prose.

def test_burst_then_refill(limiter):
    clock = FakeClock(start=0.0)
    rl = limiter(rate=2, burst=3, clock=clock)  # 2 req/s, bucket of 3

    timeline = [(0.000, True), (0.050, True), (0.100, True),  # burst drains
                (0.450, False), (0.950, False),               # too soon
                (1.100, True)]                                # ~1s: 2 tokens back
    for t, expected in timeline:
        clock.now = t
        assert rl.allow("key-a") is expected, f"at {t}s"

Ten lines, runs in microseconds, and it catches the classic generated-code bugs: refill arithmetic that rounds in the client's favor, integer division silently truncating fractional tokens, and state that's accidentally global β€” where exhausting key-a

's bucket starts denying key-b

. That last one is worth an explicit test with two keys, because it's invisible in every single-key demo the model was trained on.

If you're prompting for this code, put the seam in the prompt: "accept a clock/now parameter; no direct system time calls." You'll get more testable output, and you've also created a mechanical review rule β€” grep the diff for direct clock reads and reject on sight. That's a check a reviewer (or CI) can apply without understanding the algorithm, which is precisely what scales when the volume of generated code outstrips human attention.

The ecosystem already voted #

If injectable time sounds like ceremony, notice that platform teams have spent the last few years building it into their foundations. Go 1.25 stabilized testing/synctest, which runs a test in a "bubble" where the

time

package itself is fake and only advances when every goroutine is durably blocked β€” five-second sleeps complete in microseconds, deterministically. .NET 8 shipped the abstraction with a first-party

TimeProvider

FakeTimeProvider

you Advance()

by hand. Tokio has let Rust tests and auto-advance the runtime clockfor years, and

Jest's fake timersare table stakes in JavaScript.

And the canonical Go limiter, golang.org/x/time/rate, bakes the seam into its public API:

AllowN(now, n)

takes the timestamp as an argument. The maintainers of the reference implementation decided time is an input, not ambient state.That convergence matters for the AI-codegen era more than any of those teams intended. Everyone's review advice for generated code says the same vague thing β€” "verify behavior, don't trust vibes" β€” but verification has a cost, and the fake clock is what makes the cost low enough that you'll actually pay it. Deterministic seams turn "review this algorithm" into "check this table," and tables are cheap.

What the fake clock can't tell you #

Be honest about the limits, because a green deterministic suite is its own trap. A single-threaded timeline proves the logic, not the locking β€” a limiter can pass every boundary test and still corrupt its bucket state under concurrent access, so you still want a race-detector pass or a hammering test with real threads. It also says nothing about capacity or memory growth across a few hundred thousand keys.

And the technique mostly evaporates for distributed limiters. If your bucket lives in Redis and the arithmetic runs in a Lua script against Redis's own TIME

, there's no seam to inject β€” you're back to integration tests and careful reading. That's a real argument for keeping generated limiters at the edge of what they're good for: single-process, best-effort throttling. For the endpoints where a limiter failure costs money β€” payments, auth, anything compliance-shaped β€” use the gateway's limiter or a maintained library, not forty lines from a chat window. On that point the original post and I fully agree.

The transferable lesson is bigger than rate limiting, though. Retry backoff, cache TTLs, token expiry, schedulers β€” anything an LLM writes that touches time, randomness, or I/O should be reviewed at the seam first. Does the nondeterminism come in as a dependency you control? If yes, twenty minutes buys you a verdict instead of a vibe. If no, send it back before you bother reading the math. The model will happily regenerate; your incident channel is less forgiving.

Sources & further reading #

The Fake Clock Is the Part of an AI-Written Rate Limiter Worth Reviewingβ€” dev.to - Testing Time (and other asynchronicities)β€” go.dev - Testing with FakeTimeProviderβ€” learn.microsoft.com - tokio::time::β€” docs.rs - golang.org/x/time/rateβ€” pkg.go.dev

Rachel GoldsteinΒ· Dev Tools Editor

Rachel has been embedded in the developer tooling ecosystem for nearly eight years, covering everything from IDE wars and package-manager drama to the quiet rise of AI-assisted coding. She has a soft spot for open-source maintainers and an unhealthy number of terminal emulators installed on a single laptop.

Discussion 0 #

No comments yet

Be the first to weigh in.

── more in #artificial-intelligence 4 stories Β· sorted by recency
── more on @taylor wang 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain β€” perfect for shipping the agent you just read about.

$git push zahid main
β†’ Live at https://your-agent.zahid.host βœ“
Get free account β†’ Pricing
from €0/mo Β· no card required
LIVE [news/don-t-review-ai-code…] indexed:0 read:6min 2026-08-19 Β· β€”