# 0034 · A script has half a second, and is checked within the time its runs get

**Status:** Accepted · 2026-11-05. It changes the run time that [0023](https://codna.me/docs/adr/0023-automations-reach-outside.md),
[0025](https://codna.me/docs/adr/0025-people-own-connections.md), [0028](https://codna.me/docs/adr/0028-scripts-call-the-apis-they-read.md),
[0030](https://codna.me/docs/adr/0030-a-calls-answer-runs-the-next-step.md) and [0031](https://codna.me/docs/adr/0031-a-step-can-run-later.md) quote as
100 ms. The sandbox ([0007](https://codna.me/docs/adr/0007-quickjs-sandbox.md)) does not change.

## Context

A run had 100 ms (`CODNA_AUTOMATION_TIMEOUT`). That was set when scripts were a few lines that
shared a page or added a tag. Since 0026 and 0027, a script can be a report: it takes a day's
numbers and writes the page itself, with no model.

The first one is a customer's daily campaign report. The CDP posts about 21 KB of counts to an
incoming connection, and a 12 KB script turns them into tables. On 2026-11-05 it ran out of time on
the real day's numbers, at 120 ms, on the host that runs the hosted instances. On a laptop the same
run takes 30 to 40 ms. About half of that is QuickJS parsing the script itself, which no script
can avoid. The rest is formatting a few thousand table cells.

Two more things showed up:

- **Registration ignored the setting.** `Check` ran with the sandbox's default, not the instance's
  `CODNA_AUTOMATION_TIMEOUT`. A script slower to load than 100 ms was refused on an instance
  configured to give it more.
- **Only sources get extra time.** Data read from a source adds a second for each MB (0025). A body
  posted to an incoming connection, up to 1 MB, gets nothing.

## Decision

1. **A run has 500 ms by default.** It stays synchronous, with no event loop, and has nothing to
   wait on. The limit still stops a script that loops, and 500 ms is still well under any time a
   person would notice.
2. **A script is checked within its instance's limits.** `Runtime.Check` takes the limits, and the
   automation service checks scripts with the same ones the runner gives their runs.

## Consequences

- A report that builds its own tables from a day's data fits, with room for a busier host or a
  larger day.
- A script stuck in a loop now takes 500 ms of a worker to stop, not 100 ms. A run is still one
  goroutine in a bounded pool, and a timed-out run applies nothing, as before.
- An instance can still set `CODNA_AUTOMATION_TIMEOUT` lower or higher, and registration now
  agrees with it.
- The ADRs above that say "100 ms" describe the limit when they were written. The current number is
  in `docs/automations.md` and `docs/reference/settings.md`.

## Alternatives rejected

- **Make the script faster.** Minifying it and replacing regular expressions with plain string code
  saved about 30%. That leaves it near the limit on an average day, and every author of a report
  would have to learn the same tricks.
- **Give an incoming body a second per MB, as sources get.** For 21 KB that is 21 ms, not enough.
  Most of the cost is the script, not the data.
- **Raise it for that one instance only.** The limit is the platform's, and every instance has the same host
  and the same kind of report coming.
