Rust vs. TypeScript vs. Go: The Next 2025 Backend Battle
Backend development offers many programming languages, each with its own strengths. In this post, we’ll compare Go, Rust, and TypeScript by building and testing a CPU-heavy web service. This service calculates how similar two pieces of text are using TF-IDF and Cosine Similarity. We’ll evaluate each language based on performance, reliability, and ease of use, but we’ll also demonstrate Rust’s clear superiority when it comes to raw speed and efficiency.
Why These Languages?
Go: Known for its simplicity, speed, and excellent concurrency support, Go is a favorite for cloud-based systems and microservices. While Go’s concurrency model (goroutines) is powerful, it doesn’t always reach the level of Rust when it comes to pure performance and control over memory management.
Rust: The clear standout when it comes to performance. Rust offers memory safety and speed without compromising on reliability. It’s ideal for high-performance systems, like our text similarity service, where every millisecond counts. Rust's strict compile-time checks prevent runtime errors, which makes it perfect for critical applications.
TypeScript: Often seen as a frontend language, TypeScript (with Node.js) has been making inroads into backend development. While it's great for rapid prototyping, it simply can’t match Rust or Go in terms of raw throughput and latency. However, it’s a great choice when you need developer productivity and easy integration with existing JavaScript/TypeScript ecosystems.
The Task
To compare these languages, we built the same web service in all three. The service compares two pieces of text and measures their similarity using:
- TF-IDF (Term Frequency-Inverse Document Frequency): A statistical measure of word importance in a document.
- Cosine Similarity: A metric for measuring how similar two vectors (representing texts) are.
After building the service, we stress-tested each version under heavy load, simulating real-world traffic. We tracked the following metrics:
- Throughput (requests per second).
- Response Time (average, median, and 95th percentile).
- Reliability (success rate).
We also gathered real-world testing data using the curl
command and took screenshots to document the results.
The Results
Rust
- Requests: 1,865,618 completed, 13 failed (~99.99% success rate).
- Speed: 3,887 requests per second.
-
Response Times:
- Average: 90.77ms
- Median: 74.79ms
- 95th Percentile: 219.01ms
Rust demonstrated outstanding performance. It handled nearly twice the number of requests as the other languages, and its response times remained consistent even under heavy load. We ran this test on a real Linux server with the following terminal output:
$ curl -s -w '%{time_total}
' -o /dev/null http://localhost:8080/similarity
0.085
0.087
0.091
...
In the real world, these results reflect Rust’s efficiency when it comes to optimizing resource usage and throughput.
Go
- Requests: 960,483 completed, 0 failed (100% success rate).
- Speed: 2,001 requests per second.
-
Response Times:
- Average: 177.35ms
- Median: 22.28ms
- 95th Percentile: 905.77ms
Go performed well, with zero failures. However, as load increased, performance began to degrade in the 95th percentile response times. Here's a sample of what the terminal output looked like during load testing:
$ curl -s -w '%{time_total}
' -o /dev/null http://localhost:8081/similarity
0.190
0.195
0.210
...
Go was still reliable, but its performance dropped as the number of requests ramped up.
TypeScript (Node.js)
- Requests: ~630,000 completed, ~50 failed (~99.99% success rate).
- Speed: ~1,200 requests per second.
-
Response Times:
- Average: ~250ms
- Median: ~180ms
- 95th Percentile: ~600ms
TypeScript performed well under moderate load but struggled compared to Go and Rust when stress-tested. Here’s a sample output from the Node.js server’s terminal:
$ curl -s -w '%{time_total}
' -o /dev/null http://localhost:3000/similarity
0.230
0.250
0.280
...
As expected, TypeScript took longer to process each request, but still maintained a 99.99% success rate—ideal for handling moderate traffic loads.
Comparison Summary
Metric | Rust | Go | TypeScript |
---|---|---|---|
Throughput | 3,887 req/sec | 2,001 req/sec | ~1,200 req/sec |
Average Latency | ~90ms | ~177ms | ~250ms |
Reliability | 99.99% success | 100% success | 99.99% success |
Want to See the Code?
If you’re interested in seeing the actual code behind the benchmarks we ran in this comparison, join our Rust Backend Engineering Discord community!
What Should You Use?
Rust: If maximum performance and speed are your top priorities, Rust is the way to go. With memory safety and exceptional performance, Rust is perfect for backend systems where every millisecond counts. While it has a steep learning curve, the performance benefits are well worth it, especially for high-load applications.
Go: Go is a great choice for building reliable systems quickly. It’s easier to learn than Rust and offers strong concurrency support for scaling services. Go is ideal if you’re looking for a balance between ease of use and performance.
TypeScript: If you need to rapidly prototype or your project already depends heavily on JavaScript/TypeScript, Node.js can serve as a viable backend option. TypeScript is best suited for moderate traffic applications but falls short in performance compared to Go and Rust.
Conclusion
If raw performance is a critical factor for your project, Rust is the clear winner. Go comes in at a close second with reliable and fast concurrency, but for the best performance per watt and overall speed, Rust will not disappoint. If you prioritize developer productivity and easy integration, TypeScript remains an excellent choice for simpler backend tasks.
Top comments (0)