Replay

Replay tests a new release against your real recent traffic before it goes live. It makes two copies of your app from the same moment, one running the live release and one running the new release, sends your recent requests to both, and shows you every difference: new errors, changed status codes, changed responses and slower routes.

Use it on any build that isn't live yet, for example after deploying to a staging slot, and promote only when it's clean.

Start a replay

On the app's Rewind tab, under Replay, pick the release, how far back to read traffic and how many requests to send, then press Replay. It takes a few minutes: most of that is making the two copies.

From the CLI:

velixir deploy --slot staging       # build the new release
velixir replay v43 --wait           # block until the verdict

--window takes 1h to 7d (default 24h), --max takes 10 to 1000 (default 300), and --keep-copies leaves both copies running afterwards so you can look at them.

What it sends

Your most requested GET and HEAD requests from the access logs in the window, plus a sample of the rarer ones, so less visited pages get a look too. Only GET and HEAD are replayed, the requests that shouldn't change data. Access logs are kept for a day on the Free plan and a week on paid plans, which caps how far back it can read.

If the app has no recent traffic, Replay follows the links from its home page instead.

Requests are sent without cookies or sign-in headers, so pages behind a login answer as they would to a signed-out visitor.

The two copies

  • Both are made from the same moment, each with its own copy of your databases and caches, so a difference comes from the code and not the data. Nothing replayed touches your live data.
  • Both run your current env vars and settings, so the code is the only thing that differs.
  • Neither can reach the internet. They have your env vars, live API keys included, so they're sealed: they reach their own data and nothing else.
  • Rate limits and the WAF are off on the copies, because every request comes from one address and Replay is measuring your app, not the edge.
  • They're discarded when the replay finishes, unless you kept them.

Reading the report

The live release answers every request twice. Anything that changes between those two answers on its own, like a timestamp or a generated id, is ignored when comparing with the new release.

Finding Severity
A request that worked now fails with a 5xx or a timeout High
A request that worked now returns a 4xx High
Any other status code change Medium
A route whose 95th percentile time grew by half and by at least 100 ms Medium
A response that changed (named JSON fields, or the body) Low
A request that failed now works Info

The verdict is regressions when there's a high finding, review when the worst is medium, and clean otherwise. With --wait, the CLI exits with code 1 on regressions, so a CI job can stop before promoting.

From the API or an agent

  • POST /api/v1/apps/{id}/replays with { "releaseId": "...", "windowHours": 24, "maxRequests": 300 }
  • GET /api/v1/replays/{id} for progress and the report, GET /api/v1/apps/{id}/replays for the list.

In the MCP server these are replay_release and replay_status, so an agent can test its own release and fix what Replay finds before you look.

Cost and plans

Replay itself is included. The two copies are billed by the hour like any app and database while they run, which for a replay is usually under an hour. They run on your app's plan, so a Free app needs a paid plan first (the Free plan includes one app).