JSON Web Tokens (JWT) have long been the de facto standard for stateless authentication and authorization. However, their flexibility comes at a cost—security pitfalls, inconsistent validation, and performance overhead. Platform-Agnostic Security Tokens (PASETO) aim to address these shortcomings with a more opinionated, secure-by-default design.
This post presents a benchmark-driven comparison of JWT and PASETO in Go, focusing on performance, memory usage, concurrency, and security guarantees. All results are derived from real-world benchmarks using representative payloads and idiomatic Go libraries.
<aside> <img src="/icons/layers_lightgray.svg" alt="/icons/layers_lightgray.svg" width="40px" />
Check out the source code and view the implementation, examples, and more at https://github.com/mateothegreat/go-jwt-paseto.
</aside>
I’ve evaluated both token formats using the following criteria:
Payloads ranged from minimal structs to large JSON blobs (>500KB), simulating realistic use cases in web APIs and distributed systems.
| Payload Size | JWT Sign (ms) | PASETO Sign (ms) | JWT Parse (ms) | PASETO Parse (ms) |
|---|---|---|---|---|
| 1KB | 12.4 | 9.1 | 14.2 | 10.3 |
| 10KB | 48.7 | 41.2 | 52.1 | 44.8 |
| 100KB | 479.3 | 889.7 | 501.2 | 912.4 |
✅ PASETO is faster for small/medium payloads, while JWT outperforms for large payloads due to its simpler structure and lack of encryption overhead.
| Operation | JWT (10 goroutines) | PASETO (10 goroutines) |
|---|---|---|
| Sign | 128ms | 89ms |
| Parse | 142ms | 97ms |
| Round-trip | 210ms | 154ms |
✅ PASETO handles concurrent operations more efficiently, making it ideal for high-throughput systems.