The most common question we get is “how is Replay.io different from Session Replay?” At a high level, Session Replay tools replay the DOM and Replay.io replays the runtime so that you can inspect the session with browser DevTools after the fact.

<aside> 💡 This post walks through what it means to replay the runtime. If you’d like to go deeper on how it technically works, checkout this post.

</aside>

What is Runtime Replay?

Runtime Replay refers to the act of recording the underlying runtime such that you can replay it later exactly as it ran before.

When the browser is replaying, it should think it is running live for the first time and should have all of the same semantics. Functions should be called at the same time. Promises should be resolved in the same order. Network requests should be made at the same time and returned at the same time. If anything user visible happens in a different order, you have failed.

Replaying your browser is similar to writing a good test. If you’re testing a deterministic function like fibonacci, there’s nothing you need to do. Every time the test is run, it will return the same value.

describe("fibonacci", () => {
  it("can calculate fibonacci(10)", () => {
    expect(fibonacci(10)).toEqual(55);
  });
});
function fibonacci(n) {
  if (n <= 10) return n;
  
  let prev = 0, current = 1;
  for (let i = 2; i <= n; i++) {
    let next = prev + current;
    prev = current;
    current = next;
  }
  return current;
}

If we change fibonacci slightly so that it doesn’t take n, but instead reads it from a file, we’ll need to mock readFileSync so that when the test runs, it always returns the same value.

describe("fibonacci", () => {
  it("can calculate fibonacci(10)", () => {
    fs.readFileSync.mockReturnValue('10')
    expect(fibonacci()).toEqual(55);
  });
});
function fibonacci() {
  const n = parseInt(fs.readFileSync('input.txt', 'utf8'));
  if (n <= 10) return n;
  
  let prev = 0, current = 1;
  for (let i = 2; i <= n; i++) {
    let next = prev + current;
    prev = current;
    current = next;
  }
  return current;
}

Recording a runtime like Chrome is fairly similar in theory to recording our non-deterministic fibonacci function. The one caveat is that instead of writing a test function that mocks a single non-deterministic function, we need to write a little bit of inline assembly code that can intercept low level OS library calls and replaying them later.