Performance

Benchmark

I benchmarked @ttsalpha/qrcode against the three most popular React QR libraries: qrcode.react, qr-code-styling, and react-qr-code — covering true cold start, SSR latency, throughput, sequential batch, bundle size, and feature completeness.

Environment: ubuntu-latest · Node.js v24.16.0 · ECL pinned to M · median / p95 / p99 · June 2026

Source: github.com/ttsalpha/qrcode-benchmark

Feature Comparison

Key capabilities across all four libraries — before we look at numbers.

Feature@ttsalpha/qrcodeqrcode.reactqr-code-stylingreact-qr-code
Output formatsSVG · PNGSVG · CanvasSVG · Canvas · PNGSVG only
Logo supportImage URL + React nodeImage URLImage URL
Auto ECL for logo✓ automanual onlymanual only
Custom dot & corner styles
Standalone string API
SSR / Edge runtime browser only
Error correction level
QR version control
Zero dependencies✓ (0)✓ (0) (1 dep) (2 deps)
TypeScript built-in
ESM + CJS dual export
Accessibility (aria / title)
Bundle size (gzip)8.7 KB6.1 KB13.8 KB∼45 KB (w/deps)

Unique input per render, 3 s window

Each call receives a distinct URL — no lib can benefit from caching. Higher r/s is better.

@ttsalpha/qrcode (toSVGString)
2,126 r/s
qrcode.react (SVG)
1,714 r/s
@ttsalpha/qrcode (React)
1,254 r/s
react-qr-code
1,017 r/s
qr-code-styling (async)
79 r/s

toSVGString reaches 2,126 r/s — 1.2× faster than qrcode.react and 27× faster than qr-code-styling. Runs sync with no React or DOM overhead, ideal for server-side and batch workloads.

Fresh process per round via child_process.fork

10 rounds each. Measures real Lambda / edge cold-start: import + first render with zero JIT warmup.

LibraryImport (ms)Import p951st render1st p952nd render
@ttsalpha/qrcode (toSVGString)30.25 ms32.8 ms7.026 ms7.244 ms1.369 ms
@ttsalpha/qrcode (React)29.99 ms30.95 ms15.41 ms16.228 ms2.795 ms
qrcode.react27.59 ms27.96 ms14.817 ms17.839 ms4.732 ms
react-qr-code32.34 ms35.32 ms14.921 ms17.573 ms8.274 ms
qr-code-styling4.55 ms4.85 ms58 ms60.281 ms37.103 ms

toSVGString first-renders in 7.026 ms — 2× faster than qrcode.react (14.817 ms). qr-code-styling has the fastest import (4.55 ms) but the slowest first render (58 ms), and stays slow at 37 ms on the second render because its DOM-based async pipeline does not JIT-warm effectively.

Real-world payloads

12 varied payloads (short URL, long URL, vCard, numeric, WiFi, mailto, tel…), 10 rounds, p99 included.

LibraryMedian (ms)p95 (ms)p99 (ms)
@ttsalpha/qrcode (toSVGString)1.2561.2721.272
@ttsalpha/qrcode (React)2.0132.2862.286
qrcode.react2.412.8392.839
react-qr-code3.2884.1294.129
qr-code-styling Not SSR-safe

toSVGString is 1.9× faster than qrcode.react and 2.6× faster than react-qr-code across 12 mixed payloads. Tight p99 (1.272 ms) means latency stays predictable even with complex inputs like vCard or WiFi configs.

Burst of N renders, single thread

Node.js is single-threaded — React renders run sequentially. Batch=100 (qr-code-styling: 20). 10 rounds.

LibraryBatchMedian batch (ms)p95 batch (ms)Avg per render (ms)
@ttsalpha/qrcode (toSVGString)100115.4115.981.154
qrcode.react100142.91146.421.429
@ttsalpha/qrcode (React)100187.7191.31.877
react-qr-code100230.86237.742.309
qr-code-styling20551.79578.3727.59

toSVGString completes 100 renders in 115.4 ms median (1.154 ms/render) — 1.24× faster than qrcode.react. qr-code-styling takes 552 ms for just 20 renders; at that rate, 100 renders would take ~2,760 ms.

Custom dot shapes + corner styles

ECL=H (logo-safe), size=512 px. Only @ttsalpha/qrcode and qr-code-styling support custom styling.

@ttsalpha/qrcode (toSVGString)
0.622 ms
@ttsalpha/qrcode (React)
1.136 ms
qr-code-styling (async DOM)
12.231 ms

@ttsalpha/qrcode renders styled QR codes 20× faster than qr-code-styling — while remaining SSR-safe, sync, and DOM-free. qr-code-styling requires a browser environment (JSDOM polyfill for Node.js/Edge) with an async API that does not scale.

qrcode.react and react-qr-code have no styling API.

Per-type render time

500 samples each, p99 included. Lower is better.

Data type@ttsalpha util@ttsalpha Reactqrcode.reactreact-qr-code
Short URL0.447 ms0.928 ms0.55 ms1.001 ms
Numeric (20 digits)0.264 ms0.724 ms0.425 ms1.003 ms
AlphaNumeric0.447 ms0.92 ms0.595 ms0.955 ms
Unicode (Japanese)0.665 ms0.834 ms0.797 ms1.354 ms
Long URL (120 chars)1.744 ms2.377 ms1.732 ms3.054 ms
vCard1.453 ms2.032 ms1.443 ms2.592 ms

toSVGString wins on 4 of 6 data types. qrcode.react edges ahead on long URL (1.732 ms vs 1.744 ms) and vCard (1.443 ms vs 1.453 ms) — both within 1%, negligible in practice.

5,000 renders, unique input

Heap sampled at baseline, peak, and final. Near-zero drift across all libraries.

LibraryBaselinePeakFinalDrift
@ttsalpha/qrcode (toSVGString)44.54 MB44.55 MB44.56 MB+0.02 MB
@ttsalpha/qrcode (React)44.53 MB44.61 MB44.55 MB+0.02 MB
react-qr-code44.58 MB44.62 MB44.57 MB−0.01 MB
qrcode.react44.63 MB44.72 MB44.56 MB−0.07 MB

All libraries show excellent memory behavior — peak stays within 0.18 MB of baseline across 5,000 renders with unique inputs. No signs of leaks in any library.

gzip + dependencies

LibraryMin (KB)Gzip (KB)DependenciesActual total
qrcode.react16.36.1016.3 KB
@ttsalpha/qrcode28.58.7028.5 KB
react-qr-code23.48.52~45 KB ⚠️
qr-code-styling46.913.8146.9 KB

react-qr-code ships 23 KB but silently pulls in qrcode-generator (~40 KB) and prop-types (~1 KB) — nearly double the apparent size.

Capability comparison

Feature@ttsalpha/qrcodeqrcode.reactqr-code-stylingreact-qr-code
SVG output
Canvas output
PNG export
toSVGString() — sync, no DOM
SSR / Edge runtime safe
Zero dependencies
Dot shape styles
Corner styles
Logo — image URL
Logo — any React node
Error correction level
QR version control
TypeScript built-in
ESM + CJS dual export
Accessibility (aria / title)
React 18+ support
React 16 / 17 support
Score15 / 1712 / 1711 / 178 / 17

Rankings

Category@ttsalpha/qrcodeqrcode.reactqr-code-stylingreact-qr-code
Throughput#1#2#3
True cold start#1#2#3
SSR latency#1#2#3
Sequential batch#1#2#3
Styled QR#1#2
Bundle size#2#1#3#4
Feature score#1#2#3#4

Reproduce

All benchmark scripts are open source. Clone and run locally.

Main benchmark
pnpm bench # node --expose-gc benchmark.mjs
Cold start benchmark
node benchmark-coldstart.mjs

When to Choose

  • Best overall for React 18+
  • Need the fastest true cold start — 2× faster than qrcode.react in a fresh process
  • Need toSVGString for SSR, email templates, or batch generation
  • Need styled QR that works server-side
  • Need logo as any React component
  • Want zero dependencies
  • Bundle size is the primary constraint (6.1 KB gzip)
  • Targeting React 16/17 legacy projects
  • Need Canvas output alongside SVG
  • Simplest possible API is sufficient
  • Browser-only, no SSR requirement
  • Willing to accept ~20× slower styled render times
  • No strong reason to choose over the others
  • Fewest features, slowest renders
  • Hidden bundle cost from dependencies