Summary
Pay-As-You-Go boxes with keepAlive: false are not auto-pausing at the documented 1-hour idle timeout. We have empirical data of status: "idle" boxes still alive 120+ minutes after their last activity, with no automatic transition to paused. The docs at /docs/box/overall/pricing.md (and /docs/box/overall/how-it-works.md) state PayG idle timeout is "1 hour", the actual observed behavior is at least 2 hours, possibly longer.
This is not blocking us (keepAlive: false idle boxes accrue essentially zero compute cost regardless), but the docs/reality mismatch caused us several hours of confusion while investigating.
Reproduction
Test 1, POLLED box (Box.list every 5 minutes, in case polling is the issue):
const box = await Box.create({ runtime: "node", apiKey, keepAlive: false });
await box.exec.command("echo started"); // single command to confirm box is responsive
// Poll via Box.list (which per #105 should NOT reset the idle timer)
for (let i = 1; i <= 24; i++) {
await new Promise(r => setTimeout(r, 5 * 60_000));
const all = await Box.list({ apiKey });
const me = all.find(b => b.id === box.id);
console.log(`t=${i*5}min status=${me?.status} last_activity=${me?.last_activity_at}`);
}
Observed: status stays "idle" for the full 120 minutes. last_activity_at is the initial echo and never updates from the Box.list polls (consistent with #105 reply, Box.list does NOT count as activity). The test script terminates without ever observing a transition to paused.
Test 2, UNTOUCHED box (zero polling, single direct GET after 60+ min):
const box = await Box.create({ runtime: "node", apiKey, keepAlive: false });
await box.exec.command("echo started");
// Wait 60+ minutes, then a single direct HTTP GET to verify state
const res = await fetch(`https://us-east-1.box.upstash.com/v2/box/${box.id}`, { headers: { "X-Box-Api-Key": apiKey } });
const data = await res.json();
console.log(data.status, "alive_min:", (Date.now()/1000 - data.created_at)/60);
Observed at t=60+ min: status: "idle", last_activity_at unchanged at the initial echo, keep_alive field absent (so keepAlive is false as expected).
Behavior summary
| Test |
After 5 min |
After 30 min |
After 60 min |
After 120 min |
| Polled box (Box.list every 5 min) |
idle |
idle |
idle |
idle |
| Untouched box (no polls at all) |
idle |
idle |
idle (still being measured) |
n/a |
Per maintainer reply on #105, the activities that reset the idle timer are: box.exec.command, box.files.*, git operations through the Box API, SSH sessions, scheduled runs. Box.list and GET /v2/box/{id} are not listed. We verified last_activity_at stays unchanged across our polls, so the timer is in fact not being reset, yet the box doesn't auto-pause within the documented 1-hour window.
What we expected
Per /docs/box/overall/pricing.md:
Pay as You Go idle timeout: "1 hour"
Per /docs/box/overall/how-it-works.md:
"If a box sits idle with no active commands, it automatically transitions to Paused after an idle timeout."
We expected the polled and untouched boxes to transition to paused around the 60-minute mark.
Suggested fixes
Either:
- Update the docs to reflect the actual auto-pause timing on PayG (whatever it actually is, appears to be 2+ hours).
- Or, if 1 hour is the intended target, audit why auto-pause is not firing in this account.
Environment
@upstash/box: 0.4.1
- Node.js: 20.19
- Box runtime:
node, size small
- Account: PayG plan,
stefan@vanila.io
- Test box IDs (already cleaned up):
working-shrew-01354, neat-hornet-89278
Summary
Pay-As-You-Go boxes with
keepAlive: falseare not auto-pausing at the documented 1-hour idle timeout. We have empirical data ofstatus: "idle"boxes still alive 120+ minutes after their last activity, with no automatic transition topaused. The docs at/docs/box/overall/pricing.md(and/docs/box/overall/how-it-works.md) state PayG idle timeout is "1 hour", the actual observed behavior is at least 2 hours, possibly longer.This is not blocking us (
keepAlive: falseidle boxes accrue essentially zero compute cost regardless), but the docs/reality mismatch caused us several hours of confusion while investigating.Reproduction
Test 1, POLLED box (Box.list every 5 minutes, in case polling is the issue):
Observed: status stays
"idle"for the full 120 minutes.last_activity_atis the initial echo and never updates from the Box.list polls (consistent with #105 reply, Box.list does NOT count as activity). The test script terminates without ever observing a transition topaused.Test 2, UNTOUCHED box (zero polling, single direct GET after 60+ min):
Observed at t=60+ min:
status: "idle",last_activity_atunchanged at the initial echo,keep_alivefield absent (so keepAlive is false as expected).Behavior summary
Per maintainer reply on #105, the activities that reset the idle timer are:
box.exec.command,box.files.*, git operations through the Box API, SSH sessions, scheduled runs.Box.listandGET /v2/box/{id}are not listed. We verifiedlast_activity_atstays unchanged across our polls, so the timer is in fact not being reset, yet the box doesn't auto-pause within the documented 1-hour window.What we expected
Per
/docs/box/overall/pricing.md:Per
/docs/box/overall/how-it-works.md:We expected the polled and untouched boxes to transition to
pausedaround the 60-minute mark.Suggested fixes
Either:
Environment
@upstash/box: 0.4.1node, sizesmallstefan@vanila.ioworking-shrew-01354,neat-hornet-89278