Rust vs Python for Backend: Practical Comparison with Code Examples

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Rust vs Python for Backend: What to Choose in Practice?

Choosing a programming language for the backend is a fundamental decision that affects development speed, performance, and project maintenance costs. Python has long been the king of backend development due to its simplicity and vast number of libraries. However, Rust, a systems programming language, has rapidly entered the world of web development, offering memory safety and performance on par with C++.

In this article, we will not discuss abstract theories. We will look at specific practical scenarios: writing an HTTP server, working with a database, and handling concurrent requests. You will see how the same code looks in Rust and Python, and you will be able to make an informed choice for your next project.



Performance: When Speed Matters

Python is an interpreted language with dynamic typing. This provides flexibility, but the cost is speed. Rust compiles to machine code and has no garbage collector, making it one of the fastest languages.

Let's consider a simple example: an HTTP server that handles a GET request and returns JSON.



Python (FastAPI)

from fastapi import FastAPIimport uvicorn

app = FastAPI()

@app.get("/")async def read_root(): return {"message": "Hello, World!"}

if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=8000)


Rust (Axum)

use axum::{Router, routing::get, Json};use serde_json::{Value, json};use std::net::SocketAddr;

async fn root() -> Json { Json(json!({"message": "Hello, World!"}))}

#[tokio::main]async fn main() { let app = Router::new().route("/", get(root)); let addr = SocketAddr::from(([0, 0, 0, 0], 8000)); println!("Server running on {}", addr); axum::Server::bind(&addr) .serve(app.into_make_service()) .await .unwrap();}

Test results (wrk, 100 connections, 10 seconds):

  • Python (FastAPI): ~12,000 RPS
  • Rust (Axum): ~280,000 RPS

Rust shows performance 20+ times higher. If your project is a high-load API, microservice, or real-time system, Rust is the obvious choice. Python remains a good option for prototypes and internal tools with low load.



Safety and Memory Management

Python completely handles memory management through a garbage collector. This is convenient but can lead to unexpected pauses (GC pauses) and memory leaks. Rust uses an ownership system and borrowing, which guarantees memory safety at compile time.

Let's consider an example: a function that processes a list of users and updates their balance.



Python (with a potential error)

users = [{"name": "Alice", "balance": 100}, {"name": "Bob", "balance": 200}]

def update_balance(user_list, amount): for user in user_list: user["balance"] += amount return user_list

# Suddenly someone removes an elementusers.pop(0)result = update_balance(users, 50) # Works, but logic is broken


Rust (safe code)

struct User {    name: String,    balance: i32,}

fn update_balance(users: &mut Vec<User>, amount: i32) { for user in users.iter_mut() { user.balance += amount; }}

fn main() { let mut users = vec![ User { name: "Alice".to_string(), balance: 100 }, User { name: "Bob".to_string(), balance: 200 }, ]; // The compiler will not allow accidentally changing the vector during iteration update_balance(&mut users, 50); // Attempting to use users after moving will cause a compile error // let other = users; // ownership moved // println!("{}"

Blogs

Book Recommendations