Skip to content
RECDiagnosticSDK
04 / REPLAY

Reproduce the bug on your own device.

Pick a recorded session: matching requests receive the recorded responses, everything else goes to the network untouched.
  • Recorded on a phoneA tester hits a bug. The session is saved on their phone and shared with you as a file.
  • Edited in Session StudioOpen a recorded session and change a status, a header or a body: a 500, an empty list, an expired token.
  • Created from scratch in Session StudioNo session and no backend yet? Write mock responses route by route, then export them as a session.

Session file

Dx_4f2a9c1.json

Your device

Replay active3 requests
TransferViewController10:32:08
GET/v1/beneficiariesreplay20097ms
GET/v1/limitsnetwork20088ms
POST/v1/transfersreplay422302ms

1 request not in the recording went to the network

Your app receives the responses from the file, as if they came from the server.

How to use it

Four steps, on the device.

  1. 1

    Bring the file

    Import it from the Files picker in History, or use a session recorded on this phone.

    HistoryImport trace

  2. 2

    Open it in History

    Choose the session, then Replay.

    Replay

  3. 3

    Choose the matching mode

    Strict compares the query parameters, Ignore query does not. Details below.

    Replay (strict)Replay (ignore query)

  4. 4

    Use your app

    A red border shows that replay is on. Served requests carry a REPLAY badge in Live. Stop ends the replay.

    REPLAYStop

In the Replay tab, you can leave any request out of the replay.

What happens to each request

Matched: answered from the file. Not matched: sent to the network.

Every request your app starts goes through the same checks, in this order. The first recorded request that passes them all gives its response.

  1. 1Is replay on?With replay off, nothing changes.no →
  2. 2Same method and same path?GET /v1/transactions only matches GET /v1/transactions. The domain is not compared.no →
  3. 3Can this response be replayed?The recorded response must be JSON, and the request must not be left out in the Replay tab.no →
  4. 4Same query parameters?Only in Strict mode. Ignore query skips this check.no →

yes

Answered from the file

The request never goes to the network. The SDK builds an HTTP response from the file (status, headers, body) and hands it to your app as if it came from the server.

Sent to the network

As soon as one check fails, the request leaves as usual, untouched, and gets the real server’s response.

Side by side: what is compared

Request from your appRequest in the file
MethodGETGETCompared: same
Domainapi.lumen-bank.exampleuat.lumen-bank.exampleNot compared
Path/v1/transactions/v1/transactionsCompared: same
Query parameters?sort=date&page=2?page=2&sort=dateDepends on the mode
HeadersAuthorization: Bearer eyJ…a91Authorization: Bearer eyJ…f07Not compared
Body——Not compared

Matching modes

Strict or Ignore query.

The mode only changes how query parameters are compared. Method and path always have to be the same.

Replay (strict)

Same parameters with the same values. Their order does not matter.

Replay (ignore query)

Parameters are not compared. Useful when they change on every call (a page number, a date).

In the file: GET /v1/transactions?page=2&sort=date
Replay (strict)Replay (ignore query)
GET /v1/transactions?sort=date&page=2matchmatch
GET /v1/transactions?page=3&sort=dateno matchmatch

Several matches

Several recorded requests match. Which one is served?

In a shared file, the same request is often recorded several times: a screen visited twice, a pull to refresh. For the selected mode they all match the same live request, so they form a group.

Request from your app

GET /v1/accounts

GET /v1/accounts×3same method, path and query

  1. HomeViewController10:32:04{ "balance": 1200 }Served
  2. TransferViewController10:32:09{ "balance": 1200 }Never reached
  3. HomeViewController10:32:15{ "balance": 960 }Never reached

Replay serves the first one, in navigation order. Not the last one.

Choose the response yourself, in the Replay tab

  1. 1Set Sorting to Grouped: the requests that match each other appear together, with their count.
  2. 2Turn off the requests you do not want to serve.
  3. 3Keep on only the one you want: it becomes the first in line, so Replay serves it.

GET /v1/accounts×3same method, path and query

  1. offHomeViewController10:32:04{ "balance": 1200 }Never reached
  2. offTransferViewController10:32:09{ "balance": 1200 }Never reached
  3. onHomeViewController10:32:15{ "balance": 960 }Served

Groups follow the mode: in Strict, same method, path and query; in Ignore query, same method and path. Session Studio shows the same groups before you replay.

Good to know

The rules behind the matching.

  • JSON responses onlyA request whose recorded response is not JSON is never replayed: it goes to the network.
  • Served right awayThe recorded duration is not reproduced: the response arrives immediately.
  • Check it before you replaySession Studio shows, route by route, which recorded response Replay will serve.

An open problem

Matching on the whole request.

Our first goal was a complete matching: same method, same path, same headers, same body. On real sessions, it refused requests that were obviously the same.

Recorded on Monday

POST /v1/transfers

Headers

Content-Type: application/jsonAuthorization: Bearer eyJhbGciOi…Qx7← changes every timeX-Request-Timestamp: 1759734610← changes every time

Body

{
  "amount": 240  "beneficiaryId": "b_1029"  "nonce": "8f1c2a…"← changes every time}
Sent today

POST /v1/transfers

Headers

Content-Type: application/jsonAuthorization: Bearer eyJhbGciOi…L2m← changes every timeX-Request-Timestamp: 1760090412← changes every time

Body

{
  "amount": 240  "beneficiaryId": "b_1029"  "nonce": "d40b9e…"← changes every time}

Compared part by part

  • Method: same
  • Path: same
  • Headers: different
  • Body: different

Full matching says no. Yet it is the same request.

A token, a timestamp, a nonce: values that change on every session, even for the same user, are enough to refuse a response that should be served. That is why Replay compares the method, the path and, in Strict mode, the query parameters, and leaves headers and body out.

Ideas we have explored

  • Skip a list of known volatile fields (tokens, timestamps, identifiers).
  • Let you choose, route by route, which fields must be equal.
  • Serve the closest recorded request instead of an exact one.

None of them is good enough yet, so the problem stays open. If you have an idea, or a case that Replay does not handle well, tell us.

Contact us