Express.js ve Fastify: Performans Karşılaştırmasında Neye Bakmalı?
Express.js uzun yıllardır Node.js ekosisteminin varsayılan HTTP çatısı. Fastify ise daha düşük ek yük ve şema tabanlı doğrulama vaadiyle ortaya çıktı. İkisini karşılaştırırken "hangisi daha hızlı" sorusu tek başına yeterli değil; çünkü ölçülen fark, uygulamanın gerçekte ne yaptığına, doğrulama katmanına ve JSON serileştirmesine bağlı olarak değişir. Bu rehber, kendi ortamınızda anlamlı bir karşılaştırma yapmanız için bir yöntem sunar.
Önkoşullar
- Node.js çalışma zamanı kurulu olmalı. Sürüme özgü davranışlar bu yazının kapsamı dışında; karşılaştırmayı kendi hedeflediğiniz sürümde yapın.
npmveyapnpmgibi bir paket yöneticisi.- Yük testi için bir araç (örneğin
autocannonveyawrk). Bu yazıda araç seçimi bir zorunluluk değil, yöntem önemli.
Sürüm numarası vermiyorum; çatıların davranışı sürümden sürüme değişebilir. Kurduğunuz sürümü package.json üzerinden sabitleyin ve karşılaştırmayı sabit sürümlerle yapın.
Karşılaştırmanın Temel Değişkenleri
İki çatıyı kıyaslarken şu katmanları ayrı ayrı düşünmek gerekir:
- Yönlendirme (routing) maliyeti: İstek yolunun handler'a eşlenmesi.
- İstek gövdesi ayrıştırma: JSON parse, form verisi, query string.
- Şema doğrulama: Gelen verinin tiplerinin ve alanlarının kontrolü.
- Yanıt serileştirme: Nesnenin JSON'a çevrilmesi.
- Middleware/plugin zinciri: Her istekte çalışan ara katmanlar.
Fastify bu katmanların bir kısmını şema tanımı üzerinden hızlandırmayı hedefler; Express ise daha esnek ve daha az kısıtlayıcı bir ara katman modeli sunar. Fark çoğunlukla doğrulama ve serileştirme aşamalarında belirginleşir.
Adım 1: Aynı İşi Yapan İki Sunucu Yazın
Karşılaştırmanın geçerli olması için iki uygulamanın aynı işi yapması gerekir. Aşağıda her iki çatıda da tek bir POST /kullanici uç noktası tanımlanıyor; gövdeden ad ve eposta alanları okunuyor ve bir yanıt döndürülüyor.
Express örneği:
const express = require('express');
const app = express();
app.use(express.json());
app.post('/kullanici', (req, res) => {
const { ad, eposta } = req.body;
if (typeof ad !== 'string' || typeof eposta !== 'string') {
return res.status(400).json({ hata: 'gecersiz govde' });
}
res.json({ ad, eposta });
});
app.listen(3000);
Fastify örneği:
const fastify = require('fastify')({ logger: false });
fastify.post('/kullanici', {
schema: {
body: {
type: 'object',
required: ['ad', 'eposta'],
properties: {
ad: { type: 'string' },
eposta: { type: 'string' }
}
}
}
}, async (request) => {
const { ad, eposta } = request.body;
return { ad, eposta };
});
fastify.listen({ port: 3000 });
Bu iki örnek işlevsel olarak benzerdir. Fastify sürümünde doğrulama şema üzerinden yapılır; Express sürümünde elle kontrol edilir. Bu fark, ölçüm sonucunu doğrudan etkiler: Fastify'a şema verdiğinizde doğrulama ve serileştirme için derlenmiş bir yol kullanılır, ancak karşılaştırmayı adil yapmak için Express tarafında da eşdeğer bir doğrulama katmanı (örneğin bir şema kütüphanesi) kullanmanız gerekir. Aksi halde "Fastify daha hızlı" sonucu, ölçtüğünüz şeyin çatı değil doğrulama yöntemi olduğu anlamına gelir.
Not: Yukarıdaki örnekler bu yazıda çalıştırılmadı; amaçladıkları davranışı göstermek için verilmiştir. Kendi ortamınızda çalıştırıp doğrulayın.
Adım 2: Ölçüm Yöntemini Sabitleyin
Anlamlı bir karşılaştırma için şu koşulları sabitleyin:
- Aynı donanım ve aynı Node.js sürümü. Farklı makinelerde alınan sonuçlar kıyaslanamaz.
- Aynı yük profili. Sabit eşzamanlılık seviyesi ve sabit süre (örneğin 30 saniye).
- Isınma turu. İlk saniyelerdeki JIT etkisini dışlamak için ölçüm öncesi kısa bir ısınma çalıştırın.
- Tek değişken. Aynı anda hem çatıyı hem doğrulama kütüphanesini değiştirmeyin.
Yük testini çalıştırırken hem gecikme dağılımına (p50, p99) hem de saniyedeki istek sayısına bakın. Tek bir ortalama değer yanıltıcıdır.
Adım 3: Sonuçları Yorumlayın
Ölçüm bittiğinde elinizde iki sayı olur; asıl iş bu sayıları bağlama oturtmaktır:
- Fark küçükse (ölçüm gürültüsü mertebesindeyse), kararınızı performans dışı kriterlerle verin: ekip alışkanlığı, ekosistem olgunluğu, mevcut kod tabanı.
- Fark belirginse, farkın hangi katmandan geldiğini izole edin. Doğrulamayı kapatıp tekrar ölçün; fark kaybolursa darboğaz doğrulama katmanındadır, çatının kendisi değil.
- Yük arttıkça iki çatının davranışı farklılaşabilir. Tek bir eşzamanlılık seviyesinde alınan sonuç genellenemez.
Yaygın Hatalar
- Doğrulamasız Fastify ile doğrulamalı Express'i kıyaslamak. En sık yapılan hata budur; sonuç yanıltıcıdır.
console.logveya ayrıntılı loglama açık bırakmak. G/Ç maliyeti ölçümü bozar. Fastify'daloggerseçeneğini, Express'te log ara katmanlarını ölçüm sırasında kapatın.- Tek istek türüyle genelleme yapmak. Yalnızca küçük JSON gövdeleriyle test edip "şu çatı her senaryoda hızlı" demek doğru değildir.
- Geliştirme modunda ölçmek. Üretim modunda çalıştırmadan alınan sonuçlar temsili değildir.
- Sürümü sabitlememek. Çatı sürümleri arasında performans davranışı değişebilir; karşılaştırmanın hangi sürümlerle yapıldığını kaydedin.
Güvenlik Etkileri
Performans tercihi güvenlik kararlarınızı gölgelememeli:
- Şema doğrulaması yalnızca tip kontrolü değildir. Gelen verinin beklenen alanlarla sınırlandırılması, fazladan alanların yok sayılması ve tip zorlamasının tutarlı olması, kütle atama (mass assignment) benzeri sorunları azaltır. Hangi çatıyı seçerseniz seçin, gövde doğrulamasını atlamayın.
- Hata mesajları bilgi sızdırabilir. Doğrulama hatalarında iç yapıyı, dosya yollarını veya şema ayrıntılarını istemciye dökmeyin.
- Gövde boyutu sınırı koyun. Büyük istek gövdeleri hem bellek hem CPU tüketir; bu hem performans hem güvenlik konusudur. Her iki çatıda da gövde boyutu sınırını açıkça ayarlayın.
- Yük dengeleme ve oran sınırlama katmanlarını çatı seçiminden bağımsız düşünün; tek bir Node.js sürecinin ham hızı, dağıtık bir kurulumun yerini tutmaz.
Karar İçin Pratik Çerçeve
Şu soruları sırayla yanıtlayın:
- Uygulamanızın darboğazı gerçekten HTTP katmanı mı, yoksa veritabanı veya dış servis çağrıları mı? İkincisiyse çatı seçimi ölçülebilir bir fark yaratmayabilir.
- Doğrulama ve serileştirmeyi şema tabanlı yapmak iş akışınıza uyuyor mu? Uyuyorsa Fastify'ın bu konudaki yaklaşımı işinize yarayabilir.
- Ekibiniz hangi ara katman modeline ve ekosisteme daha aşina? Bakım maliyeti, mikrobenchmark farkından genellikle daha belirleyicidir.
Kısacası: iki çatıyı da aynı işi yapan, aynı doğrulama seviyesinde iki uygulamayla ölçün; farkı katman katman izole edin ve kararı yalnızca sayıya değil, bakım ve güvenlik gereksinimlerinize göre verin.