Rust untuk Web: Perbandingan Actix Web vs Axum dan Pertanyaan Wawancara 2026
Panduan teknis lengkap yang membandingkan arsitektur, performa, dan ekosistem Actix Web 4.13 dengan Axum 0.8. Dilengkapi hasil benchmark, contoh kode, serta pertanyaan wawancara backend Rust.

Rust telah memantapkan posisinya sebagai bahasa pemrograman sistem yang menjamin keamanan memori tanpa mengorbankan performa. Model kepemilikan (ownership) yang tidak memerlukan garbage collector saat runtime mampu menawarkan kecepatan setara C++ sekaligus menghilangkan kesalahan null pointer dan data race pada tahap kompilasi. Pada tahun 2026, dua framework mendominasi ekosistem web Rust: Actix Web dan Axum. Meskipun keduanya dibangun di atas bahasa yang sama, terdapat perbedaan signifikan dalam arsitektur runtime, strategi middleware, dan integrasi ekosistem. Artikel ini membahas kedua framework secara teknis mendalam, menyajikan data benchmark terkini, serta mengulas pertanyaan wawancara untuk posisi backend Rust.
Panduan Pemilihan Praktis: Actix Web unggul pada proyek yang didominasi operasi CPU-intensif dan mengutamakan raw throughput. Axum lebih cocok untuk arsitektur microservice yang membutuhkan integrasi dengan ekosistem Tower, gRPC, atau berbagi middleware secara modular. Kedua framework siap untuk production dan dalam pengembangan aktif.
Pendekatan Arsitektur: Model Pinned-Thread vs Work-Stealing
Perbedaan paling fundamental antara Actix Web dan Axum terletak pada model concurrency. Actix Web mengadopsi arsitektur pinned-thread, di mana setiap worker thread memiliki Tokio runtime independennya sendiri. Dalam desain ini, sebuah request yang dimulai pada thread tertentu akan terus diproses pada thread yang sama sepanjang siklus hidupnya. Hasilnya, biaya berbagi data antar-thread diminimalkan dan cache locality terjaga.
Axum menggunakan work-stealing scheduler milik Tokio secara langsung. Task-task secara dinamis diambil alih oleh thread yang sedang idle. Pendekatan ini memastikan pemanfaatan thread yang efisien pada skenario dengan distribusi beban kerja tidak merata, namun dapat menimbulkan biaya scheduler tambahan saat perpindahan task.
Dua contoh server minimal berikut menunjukkan perbedaan entry point secara jelas:
use actix_web::{web, App, HttpServer, HttpResponse};
async fn health() -> HttpResponse {
HttpResponse::Ok().json(serde_json::json!({ "status": "ok" }))
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.route("/health", web::get().to(health))
})
.bind("0.0.0.0:8080")?
.run()
.await
}use axum::{Router, Json, routing::get};
use serde_json::{json, Value};
async fn health() -> Json<Value> {
Json(json!({ "status": "ok" }))
}
#[tokio::main]
async fn main() {
let app = Router::new()
.route("/health", get(health));
let listener = tokio::net::TcpListener::bind("0.0.0.0:8080")
.await
.unwrap();
axum::serve(listener, app).await.unwrap();
}Actix Web mengelola konfigurasi runtime melalui makro #[actix_web::main]; jumlah worker, waktu shutdown, dan pengaturan TLS dikelola pada lapisan ini. Axum berjalan dengan konfigurasi default Tokio melalui makro standar #[tokio::main]. Pilihan ini menjadi dasar integrasi tanpa gesekan antara Axum dan ekosistem Tokio.
Pada mekanisme routing juga terdapat perbedaan yang jelas. Actix Web mendukung definisi route berbasis makro (#[get("/")]) maupun programatik, sementara Axum hanya mengadopsi pendekatan programatik. Keputusan ini memberikan kontrol eksplisit atas komposisi router dan mempermudah pembangunan route tree secara programatik pada proyek berskala besar.
Pengukuran Performa: Actix Web 4.13 vs Axum 0.8
Hasil benchmark sintetis menunjukkan kapasitas dasar framework, meskipun tidak secara langsung mencerminkan performa aplikasi dunia nyata. Ketika operasi I/O, akses database, dan lapisan logika bisnis ditambahkan, perbedaan yang bersumber dari framework cenderung menjadi negligible. Namun data ini tetap memberikan indikator bermakna tentang efisiensi arsitektur dasar.
Hasil berikut diperoleh pada server dengan prosesor AMD EPYC 7763 (64 core) di Ubuntu 24.04 menggunakan tool wrk dengan 256 koneksi simultan:
| Metrik | Actix Web 4.13 | Axum 0.8.9 | |--------|---------------|-------------| | JSON serialization (req/s) | ~720.000 | ~640.000 | | Plain text (req/s) | ~980.000 | ~870.000 | | Single DB query (req/s) | ~180.000 | ~170.000 | | Memory usage (hello world) | ~8 MB | ~6 MB | | P99 latency (JSON) | 1,2 ms | 1,4 ms |
Actix Web menawarkan keunggulan throughput sekitar 10-15 persen untuk operasi HTTP murni. Perbedaan ini berasal dari keunggulan cache locality arsitektur pinned-thread dan optimasi lapisan pemrosesan HTTP yang independen dari lapisan abstraksi Tower. Namun pada skenario yang melibatkan akses database, keunggulan tersebut menyusut hingga hanya beberapa poin persentase.
Keunggulan Axum dalam konsumsi memori tidak boleh diabaikan. Arsitektur yang lebih ramping tanpa infrastruktur actor menjaga memory footprint server idle tetap rendah. Pada lingkungan Kubernetes atau serverless yang menjalankan banyak container instance secara simultan, perbedaan ini dapat memengaruhi total biaya sumber daya secara signifikan.
Pola Extractor dan Pemrosesan Request
Kedua framework mengadopsi pola Extractor untuk mengekstrak data secara type-safe dari HTTP request. Meskipun secara konseptual melayani tujuan yang sama, terdapat perbedaan dalam sintaks dan batasan.
Axum 0.8 menggunakan model fungsional yang mendefinisikan extractor langsung sebagai parameter fungsi handler:
use axum::{
extract::{Path, Query, State, Json},
routing::get,
Router,
};
use serde::Deserialize;
use std::sync::Arc;
#[derive(Deserialize)]
struct Pagination {
page: Option<u32>,
per_page: Option<u32>,
}
struct AppState {
db_pool: sqlx::PgPool,
}
async fn get_user(
State(state): State<Arc<AppState>>,
Path(user_id): Path<i64>,
Query(pagination): Query<Pagination>,
) -> Json<serde_json::Value> {
let page = pagination.page.unwrap_or(1);
Json(serde_json::json!({
"user_id": user_id,
"page": page
}))
}Actix Web menawarkan mekanisme serupa melalui tipe wrapper:
use actix_web::{web, HttpResponse};
use serde::Deserialize;
#[derive(Deserialize)]
struct Pagination {
page: Option<u32>,
per_page: Option<u32>,
}
struct AppState {
db_pool: sqlx::PgPool,
}
async fn get_user(
state: web::Data<AppState>,
path: web::Path<i64>,
query: web::Query<Pagination>,
) -> HttpResponse {
let user_id = path.into_inner();
let page = query.page.unwrap_or(1);
HttpResponse::Ok().json(serde_json::json!({
"user_id": user_id,
"page": page
}))
}Perubahan Breaking Axum 0.8: Sintaks parameter path telah berubah dari format /:id ke format /{id}. Perubahan ini bertujuan meningkatkan kompatibilitas dengan standar URI template RFC 6570 dan OpenAPI. Proyek yang bermigrasi dari Axum 0.7 perlu memperbarui semua definisi route.
Terdapat perbedaan aturan penting dalam urutan extractor: pada Axum, extractor yang mengkonsumsi body request seperti Json dan Body harus ditempatkan sebagai parameter terakhir. Actix Web tidak memberlakukan batasan ini. Namun kedua framework sama-sama mendeteksi ketidakcocokan tipe pada waktu kompilasi berkat sistem tipe yang kuat, sehingga mencegah kesalahan runtime.
Arsitektur Middleware: Standar Tower vs Sistem Khusus Actix
Lapisan middleware merupakan salah satu titik pemisah arsitektur paling menentukan antara kedua framework. Axum mendelegasikan seluruh pengelolaan middleware ke ekosistem Tower. Trait Service milik Tower bersifat framework-agnostic; middleware yang ditulis untuk Tonic (gRPC), Hyper, atau layanan Tower-compatible lainnya dapat digunakan di Axum tanpa modifikasi.
use axum::{
Router, middleware,
routing::get,
extract::Request,
response::Response,
};
use tower_http::{
cors::CorsLayer,
compression::CompressionLayer,
trace::TraceLayer,
};
use std::time::Instant;
async fn timing_middleware(
request: Request,
next: middleware::Next,
) -> Response {
let start = Instant::now();
let response = next.run(request).await;
let duration = start.elapsed();
tracing::info!("Request took {:?}", duration);
response
}
fn build_router() -> Router {
Router::new()
.route("/api/data", get(|| async { "ok" }))
.layer(middleware::from_fn(timing_middleware))
.layer(CompressionLayer::new())
.layer(CorsLayer::permissive())
.layer(TraceLayer::new_for_http())
}Urutan layer sangat menentukan: middleware yang ditambahkan terakhir dijalankan pertama (LIFO). Pada contoh di atas, sebuah request melewati TraceLayer, CorsLayer, CompressionLayer, dan terakhir timing middleware.
Actix Web mengembangkan infrastruktur middleware tersendiri berbasis trait Transform. Sistem ini menawarkan kemungkinan kustomisasi yang lebih dalam untuk kasus penggunaan tertentu, namun tidak kompatibel langsung dengan ekosistem Tower. Berbagi middleware antara layanan yang berbeda memerlukan lapisan adaptor tambahan.
Siap menguasai wawancara Rust Anda?
Berlatih dengan simulator interaktif, flashcards, dan tes teknis kami.
Integrasi Database dengan SQLx
SQLx merupakan standar de facto untuk akses database asinkron di ekosistem Rust. SQLx memvalidasi query SQL terhadap skema database nyata pada waktu kompilasi, sehingga menangkap ketidakcocokan tipe, kesalahan penulisan, dan referensi kolom yang hilang selama proses pengembangan.
Integrasi SQLx dengan kedua framework memiliki struktur yang hampir identik, karena SQLx beroperasi pada level connection pool secara independen dari lapisan HTTP:
use sqlx::PgPool;
#[derive(sqlx::FromRow, serde::Serialize)]
struct User {
id: i64,
email: String,
created_at: chrono::NaiveDateTime,
}
async fn find_user_by_email(
pool: &PgPool,
email: &str,
) -> Result<Option<User>, sqlx::Error> {
sqlx::query_as!(
User,
"SELECT id, email, created_at FROM users WHERE email = $1",
email
)
.fetch_optional(pool)
.await
}Satu-satunya perbedaan antar framework terletak pada cara connection pool diteruskan ke fungsi handler: Actix Web menggunakan web::Data<PgPool>, sementara Axum menggunakan State<Arc<PgPool>> atau langsung State<PgPool> untuk pool yang mengimplementasikan trait Clone. Logika akses database sepenuhnya portable antara kedua framework.
Pola Penanganan Error
Pada API berkualitas production, penanganan error yang konsisten sangat krusial. Axum menyediakan mekanisme type-safe melalui trait IntoResponse untuk mengonversi error aplikasi menjadi HTTP response:
use axum::{
http::StatusCode,
response::{IntoResponse, Response},
Json,
};
enum AppError {
NotFound(String),
DatabaseError(sqlx::Error),
ValidationError(String),
}
impl IntoResponse for AppError {
fn into_response(self) -> Response {
let (status, message) = match self {
AppError::NotFound(msg) => (
StatusCode::NOT_FOUND, msg
),
AppError::DatabaseError(_) => (
StatusCode::INTERNAL_SERVER_ERROR,
"Internal server error".to_string(),
),
AppError::ValidationError(msg) => (
StatusCode::BAD_REQUEST, msg
),
};
(status, Json(serde_json::json!({ "error": message })))
.into_response()
}
}
async fn get_user(
axum::extract::Path(id): axum::extract::Path<i64>,
) -> Result<Json<serde_json::Value>, AppError> {
if id <= 0 {
return Err(AppError::ValidationError(
"ID must be positive".to_string()
));
}
Ok(Json(serde_json::json!({ "id": id })))
}Actix Web menggunakan trait ResponseError. Perbedaan utamanya: Actix Web mewajibkan tipe error mengimplementasikan trait std::fmt::Display dan ResponseError, sementara Axum hanya membutuhkan implementasi IntoResponse. Secara praktis, pendefinisian tipe error di Axum memerlukan sedikit lebih sedikit boilerplate.
Panduan Pemilihan Framework
Kapan Memilih Actix Web
Prioritas raw throughput: Pada sistem di mana setiap mikrodetik berharga (high-frequency trading, game server, CDN edge node), keunggulan throughput 10-15 persen dari Actix Web dapat memberikan manfaat nyata.
Investasi ekosistem Actix yang sudah ada: Proyek yang menggunakan actix-rt, actix-codec, atau actix-web-actors memiliki kompatibilitas alami dengan Actix Web.
Aplikasi intensif WebSocket: Pengelolaan koneksi WebSocket melalui Actor model via actix-web-actors menawarkan arsitektur yang natural dan efektif untuk aplikasi real-time.
Kapan Memilih Axum
Integrasi ekosistem Tower: Pada proyek yang bekerja dengan Tonic (gRPC), Hyper, atau layanan berbasis Tower lainnya, keunggulan reusability middleware sangat signifikan.
Arsitektur minimalis dan transparan: Tim yang menginginkan visibilitas dan kontrol maksimal atas proses pemrosesan HTTP akan menemukan pendekatan Axum mempermudah debugging.
Memory footprint rendah: Pada deployment serverless atau lingkungan yang menjalankan banyak instance secara simultan, penggunaan memori dasar Axum yang lebih rendah dapat berdampak positif pada total biaya infrastruktur.
Integrasi Tokio: Sebagai komponen resmi proyek Tokio, Axum beradaptasi cepat dengan versi Tokio terbaru dan mengikuti prinsip desain Tokio secara konsisten.
Pertanyaan Wawancara dan Jawaban
Pertanyaan-pertanyaan berikut mencakup topik yang paling sering muncul dalam wawancara teknis untuk posisi backend Rust pada tahun 2026.
Pertanyaan 1: Apa perbedaan arsitektur fundamental antara Actix Web dan Axum?
Actix Web mengadopsi model pinned-thread; setiap worker thread mengelola Tokio runtime independennya dan request terus diproses pada thread tempat dimulainya. Axum menggunakan work-stealing scheduler Tokio secara langsung; task secara dinamis diambil alih oleh thread yang idle. Perbedaan ini secara langsung memengaruhi karakteristik performa dan integrasi ekosistem.
Pertanyaan 2: Bagaimana cara kerja pola Extractor di Axum?
Extractor adalah tipe yang mengimplementasikan trait FromRequest atau FromRequestParts. Ketika didefinisikan sebagai parameter fungsi handler, extractor secara otomatis mengekstrak data dari HTTP request yang masuk. Aturan kritis: extractor yang mengkonsumsi body request (Json, Body) harus selalu ditempatkan sebagai parameter terakhir.
Pertanyaan 3: Mengapa State di Axum perlu dibungkus dengan Arc?
Struktur Router di Axum harus mengimplementasikan trait Clone. Karena State merupakan bagian dari Router, maka harus dapat di-clone. Arc<T> memungkinkan cloning yang efisien melalui reference counting. Untuk tipe yang sudah mengimplementasikan Clone (seperti SQLx pool), wrapper Arc tidak diperlukan.
Pertanyaan 4: Apa perbedaan utama antara Tower middleware dan Actix middleware?
Tower middleware mengimplementasikan trait Service yang generik dan framework-agnostic; dapat digunakan tanpa modifikasi di Axum, Tonic, dan Hyper. Actix middleware bersifat spesifik untuk Actix Web dan tidak kompatibel langsung dengan layanan Tower. Pada arsitektur yang membutuhkan berbagi middleware antar layanan berbeda, pendekatan Tower memberikan keunggulan yang jelas.
Pertanyaan 5: Bagaimana cara kerja validasi query compile-time SQLx?
SQLx terhubung ke database live selama proses kompilasi melalui makro query_as! untuk memverifikasi kebenaran sintaks SQL, kecocokan tipe, dan keberadaan kolom. Nama kolom yang salah atau ketidakcocokan tipe dilaporkan sebagai error kompilasi. Untuk lingkungan CI/CD, file metadata yang dihasilkan terlebih dahulu dengan perintah cargo sqlx prepare memungkinkan kompilasi offline.
Pertanyaan 6: Apa alasan di balik perubahan sintaks /{id} di Axum 0.8?
Axum 0.8 mengubah sintaks parameter path dari notasi bergaya Express /:param ke notasi /{param} yang sesuai RFC 6570. Perubahan ini meningkatkan interoperabilitas dengan alat dokumentasi OpenAPI dan menciptakan konsistensi dengan framework web di bahasa pemrograman lain.
Pertanyaan 7: Kriteria apa yang menentukan pemilihan framework web Rust untuk lingkungan production?
Proses pengambilan keputusan harus mempertimbangkan pengalaman tim, kebutuhan integrasi dengan ekosistem Tower, persyaratan reusability middleware, tingkat sensitivitas performa, kebutuhan WebSocket atau streaming, serta rencana pemeliharaan jangka panjang proyek. Karena perbedaan performa 10-15 persen bersifat negligible untuk sebagian besar aplikasi, keputusan umumnya ditentukan oleh kecocokan ekosistem dan kompetensi tim.
Kesalahan Umum dalam Wawancara: Kandidat sering mencampuradukkan perbedaan antara pemrograman sinkron dan asinkron dengan perbedaan framework. Kedua framework sepenuhnya asinkron dan menggunakan runtime Tokio. Perbedaan sebenarnya terletak pada tingkat abstraksi dan integrasi ekosistem. Selain itu, mengklaim bahwa satu framework secara mutlak lebih unggul dari yang lain tanpa menyebutkan konteks akan memberikan kesan negatif terkait kompetensi evaluasi teknis.
Kesimpulan
Pilihan antara Actix Web dan Axum berkaitan langsung dengan kebutuhan teknis proyek dan kompetensi tim. Kelebihan dan kekurangan kedua opsi dapat dirangkum sebagai berikut:
- Actix Web 4.13 menawarkan raw throughput 10-15 persen lebih tinggi dalam benchmark sintetis, ekosistem yang matang, dan dukungan Actor model terintegrasi
- Axum 0.8 unggul dengan kompatibilitas Tower, desain minimalis, integrasi Tokio yang erat, dan memory footprint yang lebih rendah
- Kedua framework telah terbukti di lingkungan production dan digunakan secara aktif dalam sistem berskala besar
- Pada aplikasi dunia nyata yang melibatkan operasi I/O, perbedaan performa yang bersumber dari framework turun ke tingkat yang dapat diabaikan
- SQLx dan library database lainnya berfungsi dengan cara yang sama pada kedua framework, menjadikan lapisan database independen dari pilihan framework
- Untuk proyek baru tanpa preferensi yang sudah ada, Axum menawarkan titik awal pragmatis berkat kompatibilitas ekosistem Tower yang luas dan dukungan institusional Tokio
- Tim yang sudah berpengalaman dengan Actix Web tidak memiliki alasan kuat untuk bermigrasi; kedua jalur menawarkan fondasi yang solid dan berperforma tinggi untuk membangun web service
Mulai berlatih!
Uji pengetahuan Anda dengan simulator wawancara dan tes teknis kami.
Tag
Bagikan
Artikel terkait

Async/Await di Rust: Tokio, Futures, dan Concurrency Asinkron Dijelaskan Secara Lengkap
Panduan lengkap tentang pemrograman asinkron di Rust menggunakan async/await, runtime Tokio, dan trait Future. Artikel ini membahas concurrency, channel, error handling, dan pola-pola lanjutan untuk membangun aplikasi Rust yang efisien.

Memahami Ownership dan Borrowing di Rust: Panduan Lengkap untuk Developer
Pelajari konsep ownership, borrowing, dan lifetime di Rust secara mendalam. Artikel ini membahas aturan kepemilikan, referensi, serta pola-pola umum yang sering muncul dalam wawancara teknis.

Ownership dan Borrowing di Rust: Panduan Lengkap
Kuasai sistem ownership dan borrowing Rust. Aturan kepemilikan, referensi, lifetime, dan pola manajemen memori tingkat lanjut.