DEV Community

Cover image for Node.js vs Rust on Cloud Run: serving a 100 KB JSON from Redis
Anderson Danilo de Souza
Anderson Danilo de Souza

Posted on

Node.js vs Rust on Cloud Run: serving a 100 KB JSON from Redis

Hi! In this post I compare Node.js and Rust on Google Cloud Run to see which one is faster.

You could argue that most of a request's time is spent on I/O, so the language shouldn't matter much. That's a fair point, so I built the most I/O-bound service I could think of. Each API does exactly one thing: connect to Redis, read a string, and return it as JSON. The only I/O is the Redis call, and there is no other business logic.

The payload is a random JSON document of exactly 100 KB (102,400 bytes). The size was an arbitrary choice: big enough to make serialization and network copies matter, small enough to be realistic.

Everything is open source, so you can reproduce it: andersondanilo/cloudrun-benchmark.

The setup

Both APIs expose a single endpoint, GET /data, which returns the JSON stored under one Redis key. Everything runs in the same region (São Paulo, southamerica-east1), and the infrastructure is created with Pulumi.

Component Details
Node.js service Cloud Run, Node.js 22 (Alpine), Fastify 5, ioredis
Rust service Cloud Run, Rust, Poem 3 (tokio), redis-rs, distroless image
Cloud Run config (both) 1 vCPU, 512 MiB, exactly 1 instance (min = max = 1), concurrency 20, southamerica-east1
Redis e2-micro VM, Debian 12, redis-server with password, maxmemory 512mb, persistence off, same zone as the services, reached over its internal IP via Direct VPC egress
Load generator e2-micro VM, Debian 12, same zone, wrk
wrk parameters 2 threads, 20 connections (matches the Cloud Run concurrency), 5 s warm-up, then a 30 s measured run
Payload Random JSON, exactly 102,400 bytes

Running a single instance per service keeps the comparison fair: both get the same CPU and memory, and neither can scale out to hide its limits.

Results

Node.js (Fastify) Rust (Poem)
Requests/sec 237.72 467.93
Transfer/sec 23.26 MB 45.79 MB
Latency (avg) 83.80 ms 42.59 ms
Latency p50 81.34 ms 42.16 ms
Latency p90 95.26 ms 48.79 ms
Latency p99 112.70 ms 58.97 ms
Requests in 30 s 7,139 14,051

Rust reached about double the requests per second (1.97x) with about half the latency at every percentile. With a fixed number of connections the two numbers are linked: 20 connections at roughly 84 ms per request is about 238 requests per second, and 20 connections at roughly 43 ms is about 468.

Caveats

  • This is one test on one machine setup, so treat the numbers as a comparison between these two stacks, not as a universal verdict on Node.js vs Rust.
  • Both VMs are e2-micro, which is a shared-core machine type. The Redis VM or the load generator may be limiting the results, especially for Rust. I didn't test whether a bigger load generator or Redis VM pushes Rust further.
  • Each service ran on a single Cloud Run instance with 1 vCPU. With more instances, both would scale out, and the gap per instance is what would matter for cost.

Conclusion

Even for a service that only reads a string from Redis and returns it, the runtime made a clear difference: Rust served twice the traffic at half the latency on the same Cloud Run configuration. My guess is that handling a 100 KB payload on every request (reading it from Redis and writing it to the socket) costs more CPU than it seems, but I didn't profile it, so that part is a hypothesis.

If you want to run it yourself, the repo has everything: both APIs, the Pulumi infrastructure, and the benchmark script.

Top comments (0)