Skip to content

JWT decode benchmarks

Generated 2026-10-10 from bench/results-docker/ by bench/compare.py, on Neoverse-N2 (aarch64), Linux. Run in Docker, one container per library, each limited to 1 CPU (pinned) and 500 MB with no swap. Each case gets 1,000 untimed decodes, then 10,000 timed.

Each decode verifies an HS256 signature and checks exp and aud, as a real caller would. Times are µs per decode: the mean over 10,000 decodes of the same token, after 1,000 untimed (lower is better); (Nx) is the speed-up vs pyjwt 2.15.1.

Typical token (661 B, 64-byte key)

library µs per decode vs pyjwt 2.15.1
ryjwt 0.1.1 → Struct 2.08 28.6x
ryjwt 0.1.1 → dict (msgspec) 2.18 27.4x
ryjwt 0.1.1 → dict (jiter) 2.57 23.2x
jsonwebtoken 11.1.0 (aws-lc-rs) → struct 3.81 15.7x
ryjwt 0.1.1 → BaseModel 4.39 13.6x
jsonwebtoken 11.1.0 (aws-lc-rs) → Value 4.76 12.5x
fast-jwt 6.3.3 7.25 8.2x
joserfc 1.7.5 27.78 2.1x
jose 6.2.12 39.45 1.5x
pyjwt 2.15.1 59.70 1.0x

Every token and key size

Fastest per row in bold.

case token B key B ryjwt 0.1.1 → Struct ryjwt 0.1.1 → dict (msgspec) ryjwt 0.1.1 → dict (jiter) jsonwebtoken 11.1.0 (aws-lc-rs) → struct ryjwt 0.1.1 → BaseModel jsonwebtoken 11.1.0 (aws-lc-rs) → Value fast-jwt 6.3.3 joserfc 1.7.5 jose 6.2.12 pyjwt 2.15.1
small-k32 231 32 1.12 (32.6x) 1.05 (34.8x) 1.17 (31.2x) 1.93 (18.9x) 2.31 (15.9x) 2.32 (15.8x) 11.52 (3.2x) 21.73 (1.7x) 44.09 (0.8x) 36.60 (1.0x)
small-k64 231 64 1.13 (32.9x) 1.05 (35.4x) 1.19 (31.3x) 1.93 (19.3x) 2.30 (16.2x) 2.30 (16.2x) 7.62 (4.9x) 21.73 (1.7x) 37.45 (1.0x) 37.17 (1.0x)
small-k256 231 256 1.14 (34.3x) 1.05 (37.2x) 1.19 (32.8x) 2.08 (18.7x) 2.30 (17.0x) 2.45 (15.9x) 4.39 (8.9x) 21.92 (1.8x) 34.74 (1.1x) 38.99 (1.0x)
small-k4096 231 4096 1.13 (68.2x) 1.05 (73.4x) 1.18 (65.5x) 3.85 (20.0x) 2.30 (33.5x) 4.39 (17.6x) 11.60 (6.6x) 23.79 (3.2x) 45.95 (1.7x) 77.13 (1.0x)
typical-k32 661 32 2.07 (28.6x) 2.17 (27.2x) 2.58 (22.9x) 3.78 (15.6x) 4.38 (13.5x) 4.74 (12.5x) 7.08 (8.3x) 27.87 (2.1x) 39.18 (1.5x) 59.12 (1.0x)
typical-k64 661 64 2.08 (28.6x) 2.18 (27.4x) 2.57 (23.2x) 3.81 (15.7x) 4.39 (13.6x) 4.76 (12.5x) 7.25 (8.2x) 27.78 (2.1x) 39.45 (1.5x) 59.70 (1.0x)
typical-k256 661 256 2.07 (30.2x) 2.17 (28.7x) 2.59 (24.2x) 3.95 (15.8x) 4.40 (14.2x) 4.87 (12.8x) 7.65 (8.2x) 28.01 (2.2x) 45.95 (1.4x) 62.51 (1.0x)
typical-k4096 661 4096 2.08 (49.1x) 2.17 (46.9x) 2.58 (39.5x) 5.72 (17.8x) 4.40 (23.2x) 6.65 (15.3x) 13.82 (7.4x) 29.93 (3.4x) 43.77 (2.3x) 101.97 (1.0x)
medium-k32 2244 32 3.71 (37.0x) 5.98 (22.9x) 7.15 (19.2x) 7.75 (17.7x) 6.35 (21.6x) 13.21 (10.4x) 12.62 (10.9x) 45.80 (3.0x) 48.20 (2.8x) 137.19 (1.0x)
medium-k64 2244 64 3.70 (37.5x) 6.06 (22.9x) 7.17 (19.3x) 7.52 (18.4x) 6.36 (21.8x) 13.24 (10.5x) 11.43 (12.1x) 45.87 (3.0x) 47.92 (2.9x) 138.68 (1.0x)
medium-k256 2244 256 3.72 (38.0x) 5.95 (23.7x) 7.14 (19.8x) 7.71 (18.3x) 6.34 (22.3x) 13.31 (10.6x) 12.05 (11.7x) 46.14 (3.1x) 50.13 (2.8x) 141.23 (1.0x)
medium-k4096 2244 4096 3.71 (48.4x) 5.99 (30.0x) 7.15 (25.1x) 9.44 (19.0x) 6.36 (28.2x) 15.10 (11.9x) 13.78 (13.0x) 47.81 (3.8x) 51.07 (3.5x) 179.68 (1.0x)
large-k32 20884 32 26.76 (39.3x) 58.75 (17.9x) 61.72 (17.0x) 58.64 (17.9x) 40.86 (25.8x) 126.25 (8.3x) 110.61 (9.5x) 258.61 (4.1x) 161.76 (6.5x) 1052.13 (1.0x)
large-k64 20884 64 26.76 (39.2x) 58.82 (17.8x) 61.60 (17.0x) 58.92 (17.8x) 40.88 (25.7x) 126.68 (8.3x) 110.84 (9.5x) 258.48 (4.1x) 161.67 (6.5x) 1049.07 (1.0x)
large-k256 20884 256 26.75 (39.3x) 59.27 (17.7x) 61.56 (17.1x) 58.57 (17.9x) 40.86 (25.7x) 126.80 (8.3x) 110.24 (9.5x) 258.01 (4.1x) 162.53 (6.5x) 1050.18 (1.0x)
large-k4096 20884 4096 26.76 (40.8x) 58.80 (18.6x) 61.78 (17.7x) 60.29 (18.1x) 40.87 (26.7x) 127.89 (8.5x) 111.18 (9.8x) 260.30 (4.2x) 165.72 (6.6x) 1090.79 (1.0x)