ShopperCove
Menu
All writingBlogTopicsCategoriesAboutRSS
Blog
Categories
Observability & SRE62All categories
Topics
sre111localhost lab102performance70python58javascript47bundle size36benchmarking35node.js35web development21typescript19benchmark16content creation15All topics
About
Loading article…

ShopperCove

Hands-on notes on developer tools, written after the tool has actually been run.

All writingBlogCategoriesTopicsAboutPrivacyRSS

© 2026 ShopperCove

On this page

  1. What I tested
  2. Is msw faster than nock?
  3. Why is axios slower under both?
  4. Should you switch from nock to msw?
  5. Sources
  6. Related
  1. Blog

nock vs msw: Should You Switch? 2.9ms vs 0.5ms

nock 14.0.17 vs msw 2.15.0 on 2,000 sequential mocked fetch calls in Node 20: 2.85 ms vs 0.49 ms per request (~5.8x); via axios 3.80 ms vs 1.41 ms (~2.7x). nock sets up faster (97 vs 208 ms), crossover near 50 requests per process.

5 October 2026·5 min read

Hands-on
On this page
  1. What I tested
  2. Is msw faster than nock?
  3. Why is axios slower under both?
  4. Should you switch from nock to msw?
  5. Sources
  6. Related

I mocked the same 2,000 sequential fetch calls in Node 20 with nock 14.0.17 and msw 2.15.0: nock took a median 2.85 ms per request, msw took 0.49 ms (about 5.8x faster). Through axios, which goes through Node's http module instead of fetch, the gap shrank to 3.80 ms versus 1.41 ms per request (about 2.7x).

Short answer: switch to msw if your Node tests mock hundreds of fetch calls, or if you want the same handlers in the browser. Stay on nock if your suite is small, leans on nock-only features like scope.done() and recorder mode, and runs fast enough today. No affiliate links in this post.

What I tested

  • Machine: 8 vCPU Intel Xeon / 15 GB RAM Linux cloud box, Node 20.19.2, tested 5 Oct 2026 (about 23:38 to 23:43 IST). Shared box; each run in a fresh Node process, one warmup per variant, then seven interleaved rounds.
  • Fixture: /workspace/bench-msw-nock/run.mjs. One mocked endpoint GET https://api.example.test/users/:id returning a small JSON object. After one check request, the script awaits 2,000 requests in a row and checks each response id. All 2,000 came back correct in every run.
  • Tools: msw 2.15.0 (setupServer, onUnhandledRequest: 'error'), nock 14.0.17 (persist(), regex path, disableNetConnect()), axios 1.20.0. Baseline: a real node:http server on 127.0.0.1 with no mocking library.
  • Timing: performance.now() around the 2,000-request loop, plus a separate number for import + setup + first request, plus the full process wall clock.
  • Findings: loop medians were msw fetch 987 ms, nock fetch 5,710 ms, real loopback fetch 955 ms; msw axios 2,813 ms, nock axios 7,594 ms, real loopback axios 1,031 ms. Setup plus first request: nock 97 ms, msw 208 ms (fetch).
  • One surprise: both libraries depend on @mswjs/interceptors 0.41, yet nock was still 5.8x slower on fetch. A static reply object instead of a reply function did not change it (5.67 to 5.73 s across three runs).
  • Not tested: msw 3.x (3.0.2 needs Node 22.12 or newer, so it would not run here), browser or service worker mode, Vitest or Jest wiring, concurrent requests, GraphQL handlers, nock recorder, Windows/macOS.

Is msw faster than nock?

VariantMedian per requestLoop for 2,000Setup + first request
msw 2.15 + fetch0.49 ms987 ms208 ms
nock 14 + fetch2.85 ms5,710 ms97 ms
msw 2.15 + axios1.41 ms2,813 ms306 ms
nock 14 + axios3.80 ms7,594 ms187 ms
real loopback server + fetch0.48 ms955 ms80 ms
real loopback server + axios0.52 ms1,031 ms165 ms

On this fixture, yes, per request. msw on fetch was about as fast as hitting a real server on loopback. nock loads faster, so a process that makes only ten requests finishes first under nock: about 126 ms (97 + 29) versus 213 ms (208 + 5). The crossover in my numbers is around 50 requests per process. A suite that mocks 500 fetch calls would spend about 1.4 s in nock versus 0.25 s in msw.

If you are also choosing the test runner, see the Jest vs Vitest post and the jsdom vs happy-dom for Vitest post.

Why is axios slower under both?

Axios in Node uses the http module, not fetch. Both libraries intercept that path by patching http.ClientRequest, and that layer cost more than fetch interception in my runs: msw went from 0.49 to 1.41 ms per request, nock from 2.85 to 3.80 ms. Without mocking, axios over loopback was 0.52 ms, so most of that extra time came from interception, not from axios. If your code calls an http-based client, expect a smaller gap between the two libraries than the fetch numbers suggest.

Should you switch from nock to msw?

SituationMy pick
Node tests with hundreds of mocked fetch callsmsw
Same request mocks wanted in browser dev and in testsmsw
Small suite, under about 50 mocked requests per test fileStay on nock; the gap is noise
You rely on scope.done() assertions or nock's recorderStay on nock, or plan to rebuild those checks
Already on Node 22.12+ and starting freshmsw 3.x is an option, but I did not test it here

Bottom line: 2,000 fetch calls took 0.99 s with msw and 5.71 s with nock on the same box. Who should not switch yet: teams with a large nock suite built on persist() chains and isDone() checks, where rewriting every mock costs more than the seconds you would save. For related test-speed choices, see the Vitest 5 upgrade post and the c8 vs nyc coverage post; for running TypeScript tests directly, the tsx vs ts-node post.

How this was made: I wrote the fixture, installed both libraries on the ShopperCove test box, timed interleaved runs in fresh processes and kept the JSON; the write-up was drafted with AI help and checked against that output.

Sources

  • 01mswjs.io/docs/
  • 02npmjs.com/package/msw
  • 03github.com/mswjs/msw
  • 04github.com/nock/nock
  • 05npmjs.com/package/nock
  • 06github.com/mswjs/interceptors

Related

  • 01shoppercove.com/blog/playwright-1-63-test-locks-october-2026
  • 02shoppercove.com/blog/nodejs-26-lts-october-2026-schedule-change
  • 03shoppercove.com/blog/pnpm-vs-npm-vs-bun
nockmswnodejsbenchmarkinghttp-mockingfetchaxiostesting

Lab evidence

What I found running this

Hands-on on ShopperCove box 5 Oct 2026 ~23:38-23:43 IST (8 vCPU Intel Xeon / 15 GB shared Linux, Node 20.19.2). Fixture: run.mjs, GET Open api.example.test JSON, 1 check request then 2000 sequential awaited requests, ids verified (2000/2000 every run). msw 2.15.0 setupServer onUnhandledRequest error; nock 14.0.17 persist + regex + disableNetConnect; axios 1.20.0; baseline node:http server on 127.0.0.1. Fresh process per run, 1 warmup, 7 interleaved rounds. Loop medians: msw fetch 987.1 ms (0.49 ms/req), nock fetch 5709.6 ms (2.85 ms/req), real fetch 955.3 ms; msw axios 2813.1 ms (1.41 ms/req), nock axios 7594.1 ms (3.80 ms/req), real axios 1031.1 ms. Setup+first request: msw fetch 207.8 ms, nock fetch 96.5 ms, msw axios 306.4, nock axios 187.3. nock static reply: 5671/5726/5689 ms (no change). Both use @mswjs/interceptors 0.41. msw 3.0.2 needs Node >=22.12 (not run). Raw: /workspace/bench-msw-nock/res-msw-nock.json. Not tested: browser/service worker, Vitest/Jest wiring, concurrency, GraphQL, recorder, Windows/macOS. No affiliate.

Notes when a lab post goes up

Occasional email for new hands-on reviews. No sequence and no sponsors.

Keep reading

  • find-up vs locate-path: 47 µs Sync vs 596 µs Async

    Hands-on6 Oct 20268 min read

  • Ky vs Axios: 9.8 KB vs 19.6 KB Gzip

    Hands-on6 Oct 20264 min read

  • Playwright vs Cypress: 1.47s vs 4.24s Smoke

    Playwright 1.55.1 Chromium vs Cypress 14.5.4 Electron on one local smoke (visit /, assert h1, click, assert). Warm medians (7 rounds after 1 warm-up): Playwright 1,466 ms vs Cypress 4,243 ms (~2.9x). Disk: PW node_modules ~12 MB + cache ~918 MB; Cypress node_modules ~23 MB + cache ~601 MB. Fixture /workspace/bench-pw-cy/.

    Hands-on6 Oct 20264 min read