Reproduce the bug on your own device.
- 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
Your device
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
Bring the file
Import it from the Files picker in History, or use a session recorded on this phone.
HistoryImport trace
- 2
Open it in History
Choose the session, then Replay.
Replay
- 3
Choose the matching mode
Strict compares the query parameters, Ignore query does not. Details below.
Replay (strict)Replay (ignore query)
- 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.
- 1Is replay on?With replay off, nothing changes.no →
- 2Same method and same path?GET /v1/transactions only matches GET /v1/transactions. The domain is not compared.no →
- 3Can this response be replayed?The recorded response must be JSON, and the request must not be left out in the Replay tab.no →
- 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 app | Request in the file | ||
|---|---|---|---|
| Method | GET | GET | Compared: same |
| Domain | api.lumen-bank.example | uat.lumen-bank.example | Not compared |
| Path | /v1/transactions | /v1/transactions | Compared: same |
| Query parameters | ?sort=date&page=2 | ?page=2&sort=date | Depends on the mode |
| Headers | Authorization: Bearer eyJ…a91 | Authorization: Bearer eyJ…f07 | Not 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).
| Replay (strict) | Replay (ignore query) | |
|---|---|---|
| GET /v1/transactions?sort=date&page=2 | match | match |
| GET /v1/transactions?page=3&sort=date | no match | match |
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
- HomeViewController10:32:04{ "balance": 1200 }Served
- TransferViewController10:32:09{ "balance": 1200 }Never reached
- 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
- 1Set Sorting to Grouped: the requests that match each other appear together, with their count.
- 2Turn off the requests you do not want to serve.
- 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
- offHomeViewController10:32:04{ "balance": 1200 }Never reached
- offTransferViewController10:32:09{ "balance": 1200 }Never reached
- 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.
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}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