Signed upload sessions expire. Event contribution windows close. Storage reservations are reclaimed. These are normal lifecycle events, but many interfaces reduce all of them to “Upload failed.” A better protocol makes expiration explicit and recoverable where policy allows it.
Distinguish three clocks
An upload workflow usually has at least three deadlines:
- the event contribution window;
- the server-side upload intent expiry;
- the short-lived storage credential expiry.
They should not share one timestamp. The event may accept contributions until midnight while a credential lasts five minutes and an intent can be renewed for an hour.
Return the clocks in the session response with server time:
{"serverNow":"2026-07-17T18:00:00Z","eventClosesAt":"2026-07-18T00:00:00Z","intentExpiresAt":"2026-07-17T19:00:00Z","credentialExpiresAt":"2026-07-17T18:05:00Z"}
The client can display useful warnings without trusting its own clock for authorization.
Model expiration by state
A credential expiring during transfer is different from an intent expiring before completion. Use stable reasons:
credential_expired -> request renewal
intent_expired -> reconcile committed parts, then renew or restart
event_closed -> stop new work, preserve local recovery guidance
Do not automatically restart from byte zero. First ask the control plane which parts were committed and whether the original object key remains valid.
Renew narrowly
A renewal endpoint should accept the upload ID and prove continuity with the guest session. It rechecks event state, file policy, rate limits, and committed size. The response returns a new credential for the same object.
Do not let the browser extend an intent indefinitely. Define a maximum session age and a bounded number of renewals. Long uploads may receive a larger initial policy based on file size and observed throughput.
Handle the closing boundary fairly
Decide what happens to an upload already transferring when the event window closes. Reasonable policies include a grace period for active sessions or a strict cutoff for sensitive events. Document the choice and apply it on the server.
The UI should say “The upload window closed while this file was transferring” rather than suggesting a network error. If local retry later is impossible, tell the guest to keep the original and contact the host.
Avoid timer-driven corruption
Client timers are advisory. Background tabs throttle JavaScript, devices sleep, and clocks change. Never delete server state merely because a browser timer fired. Each request is authorized against server time.
When the page returns from the background, refresh status before continuing. The last part may have completed even though its response never reached the page.
Preserve user intent
Keep safe local metadata about files that need attention: upload ID, event ID, filename, size, and last known committed parts. Do not persist storage credentials. If the File object cannot survive a restart, ask the user to reselect the same file and verify basic attributes before resuming.
Test every boundary
Use fake clocks to test expiry immediately before a part begins, during a response timeout, after all parts but before completion, and while the page is hidden. Verify the displayed message and final server state.
I help build Gathmo and have a commercial interest in reliable event uploads. The Gathmo help centre provides product-specific recovery guidance; the expiration model here can be used in any resumable upload system.
Expiration is not an exceptional crash. It is a state transition with policy, evidence, and a recovery path.
Top comments (0)