Geçen ay başıma gelen bir şeyi anlatmam lazım. Bir Node.js uygulaması geliştirdim — lokalde her şey tıkır tıkır çalışıyor, testler geçiyor, API endpoint’leri doğru cevap veriyor, her şey yolunda görünüyor. “Tamam, hazır” dedim ve DigitalOcean’daki VPS’e deploy ettim. Ve… hiçbir şey çalışmıyor. Hata mesajları saçma sapan, loglarda anlamsız stack trace’ler var, ne tarafa baksam farklı bir sorun çıkıyor. Aynı kod, aynı işletim sistemi, aynı Node versiyonu — en azından öyle sanıyordum.
Üç gün boyunca kafayı yedim. Cidden. Üç gün. Sonunda suçluyu buldum: PM2, terminalde gördüğüm Node.js versiyonundan bambaşka bir versiyon kullanıyormuş. Hani şu “bende çalışıyor” meme’ini herkes bilir ya — işte tam o durumun gerçek hayattaki, uykusuz gecelere mal olan, saçları döktüren versiyonu.
Sorunun Kökü: “Aynı Ortam” Diye Bir Şey Yok
Bakın şimdi. Geliştiricilerin en sık düştüğü tuzak şu: “İki makine aynı” varsayımı. Ama değil. Hiçbir zaman tam olarak aynı değil. İşletim sistemi Ubuntu 22.04 olabilir ikisinde de, node -v yazdığında ikisi de v18.17.0 gösterebilir — ama altta dönen süreçler, ortam değişkenleri, PATH sıralaması, hangi kullanıcıyla ne kurulduğu, sistem servislerinin neyi referans aldığı… bunların hepsi bambaşka olabiliyor ve siz farkında bile olmuyorsunuz.
Ben 2023’ün sonlarında bir e-ticaret projesi için tam olarak bu duruma düştüm. İstanbul’daki bir müşterinin ödeme altyapısını Node.js ile yazmıştım. Lokalde gayet düzgün çalışıyor — “mükemmel” demeyeyim, “mükemmel” kelimesi jinx getiriyor sanki (bizzat test ettim). VPS’e atınca? Ödeme callback’leri timeout yiyor, async/await’ler garip davranıyor, hiçbir şey mantıklı gelmiyor. İlk düşüncem network oldu tabi. Firewall ayarları, port yönlendirmeleri… hepsini teker teker kontrol ettim.
Şimdi gelelim işin can alıcı noktasına.
Oysa sorun çok daha basitti. Ama basit olması, kolay bulunacağı anlamına gelmiyor maalesef (ki bu çoğu kişinin gözünden kaçıyor)
PM2 ve NVM: Sessiz Katil İkili
Sorunun kaynağını anlamak için önce şunu bilmek lazım: NVM (Node Version Manager) kullandığınızda, her Node versiyonunun kendine ait bir binary yolu var. Mesela şöyle:
/home/kullanici/.nvm/versions/node/v18.17.0/bin/node
/home/kullanici/.nvm/versions/node/v16.20.0/bin/node
Siz terminalde nvm use 18 dediğinizde, o anki shell oturumunuz v18’i kullanmaya başlıyor. Güzel. Ama PM2’yi daha önce — mesela v16 aktifken — global olarak kurduysanız, PM2 hâlâ v16’nın binary’sini kullanıyor olabilir. Terminal size v18 diyor, PM2 arka planda v16 ile sessiz sedasız çalışıyor. Siz de bunu bilmeden hayatınıza devam ediyorsunuz.
Dur bir saniye, şunu da ekleyeyim: bu sadece NVM ile olan bir sorun değil. Snap ile Node kurduysanız, apt ile ayrı bir versiyon varsa, hatta Docker container’ının içinde farklı bir PATH tanımlıysa… hep aynı tuzak. Ama en yaygın senaryo kesinlikle NVM + PM2 kombinasyonu. Bu ikili, pek çok geliştiricinin hafızasına kötü bir anı olarak kazınmıştır.
Sorunu Teşhis Etmek
İlk yapmanız gereken şey — ve ben bunu üç gün sonra yaptığım için kendime gerçekten kızıyorum — PM2’nin hangi Node versiyonunu kullandığını kontrol etmek:
# Uygulamanızın detaylı bilgilerini görmek için
pm2 show uygulama-adi
# Veya doğrudan ortam değişkenlerini incelemek için
pm2 env 0
Bu komutları çalıştırdığınızda “node version” veya “exec_interpreter” gibi alanları arayın. Orada yazan versiyonla node -v çıktısı farklıysa… tebrikler, sorunu buldunuz.
Bilmem anlatabiliyor muyum, Ben kendi projemde baktığımda şok olmuştum (en azından benim deneyimim böyle). Terminal v18.17.0 diyor, PM2 ise v16.14.2 kullanıyor — ikisi arasında optional chaining, top-level await gibi ciddi özellik farkları var, kodumda kullandığım bazı ES2022 feature’ları v16’da desteklenmiyordu — itiraf edeyim, beklentimin üstündeydi —. İşte tüm o garip hataların sebebi buymuş. Üç günlük uğraşın cevabı buymuş. Hani ne farkı var diyorsunuz, değil mi? Valla insan gülüyor sonunda.
Çözüm: Adım Adım Düzeltme
Tamam, sorunu bulduk. Şimdi nasıl düzelteceğiz? Birkaç farklı yöntem var, en güvenilir olanları sıralıyorum.
Yöntem 1: PM2’yi Doğru Versiyonla Yeniden Kurmak
Bu en temiz çözüm. Lafı gevelemeden direkt adımları veriyorum:
# Önce istediğiniz Node versiyonuna geçin
nvm use 18
# Mevcut PM2 süreçlerini durdurun
pm2 kill
# PM2'yi bu versiyon altında yeniden kurun
npm install -g pm2
# PM2 ortam değişkenlerini güncelleyin
pm2 update
# Uygulamanızı yeniden başlatın
pm2 start app.js --name uygulama-adi
# Doğrulama yapın
pm2 show uygulama-adi
Ha, bu arada pm2 update komutunu atlamayın sakın. Bu komut PM2’nin daemon’ını yeniden başlatıyor ve yeni ortam değişkenlerini almasını sağlıyor. Bunu yapmadan sadece restart atarsanız, eski versiyon hâlâ geçerli olabilir. Küçük ama kritik bir adım.
Yöntem 2: Ecosystem Dosyasında Interpreter Belirtmek
Bu yöntem bence daha sağlam —. Konfigürasyonu dosyaya yazıyorsunuz, yani yarın bir gün sunucuda başka biri bir şey kurarsa veya NVM versiyonu değişirse, PM2 hâlâ doğru Node’u kullanıyor olacak. Belgelenmiş bir yapı bu.
// ecosystem.config.js
module.exports = {
apps: [
{
name: "uygulama-adi",
script: "app.js",
interpreter: "/home/kullanici/.nvm/versions/node/v18.17.0/bin/node",
env: {
NODE_ENV: "production",
PORT: 3000
}
}
]
};
Sonra bunu şu şekilde başlatıyorsunuz:
pm2 start ecosystem.config.js
Şöyle söyleyeyim, Bir arkadaşım — Ankara’da DevOps mühendisi olarak çalışıyor — geçen sene bana dedi ki: “Ecosystem dosyası olmadan PM2 kullanmak, emniyet kemeri takmadan araba sürmek gibi.” Çok haklıymış. O zamandan beri her projede ecosystem dosyası oluşturuyorum, istisnasız.
Yöntem 3: NVM Yerine Doğrudan Node Kurulumu
Hani, Eğer sunucunuzda tek bir Node versiyonu kullanacaksanız — ki prodüksiyon ortamında çoğu zaman böyledir — NVM’e ihtiyacınız olmayabilir (evet, doğru duydunuz). NodeSource repository’sinden direkt kurulum yapabilirsiniz:
# Node.js 18.x kurulumu (Debian/Ubuntu)
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs
Bu şekilde kurduğunuzda sistem genelinde tek bir Node versiyonu olur ve PM2 de onu kullanır. NVM kaynaklı PATH karmaşası neredeyse tamamen ortadan kalkar. Ama tabi birden fazla projeniz varsa ve farklı versiyonlara ihtiyaç duyuyorsanız, bu yöntem uygun değil — o zaman ecosystem dosyası yoluna gidin.
Karşılaştırma: Hangi Yöntem Kime Uygun?
| Yöntem | Avantaj | Dezavantaj | Kime Uygun? |
|---|---|---|---|
| PM2 yeniden kurulum | Hızlı, basit | NVM değişince tekrar bozulabilir | Tek seferlik düzeltme |
| Ecosystem dosyası | Kalıcı, versiyon kontrolüne girer | Path hardcode edilmeli | Ciddi prodüksiyon ortamları |
| NVM kaldırma + direkt kurulum | Temiz, sorunsuz | Birden fazla versiyon kullanılamaz | Tek proje çalışan VPS’ler |
Dikkat Edilmesi Gereken Diğer Tuzaklar
Yani, PM2 + NVM meselesi en yaygın sorun, ama tek sorun değil. VPS’e deploy ederken başınıza gelebilecek birkaç şey daha var — bunları da paylaşayım, zira hepsini bizzat yaşadım.
Dosya İzinleri ve Kullanıcı Farkları
Lokalde genellikle kendi kullanıcınızla çalışıyorsunuz. VPS’de ise bazen root — ki bu tartışılır — ile, bazen ayrı bir deploy kullanıcısıyla işlem yapıyorsunuz — ve PM2’yi root olarak başlatıp uygulamanın ihtiyaç duyduğu dosyalara başka bir kullanıcının sahip olduğu durumlar, inanın çok yaygın. EACCES hataları yağmur gibi yağıyor o zaman, hangi tarafı kapatsan öbür taraf açılıyor.
E bir de şu var: NVM, kullanıcıya özel kuruluyor. Root kullanıcısının NVM’i ile deploy kullanıcısının NVM’i farklı şeyler. Yani sudo pm2 start ile pm2 start farklı Node versiyonlarını kullanabilir. Bu ne anlama geliyor? Bunu da aklınızda tutun, sonradan “nasıl böyle bir şey olur” diye saatlerce bakarsınız (ciddiyim) Daha fazla bilgi için Whisper ve Streamlit ile Sesli AI Ajanı Kurmak: Pratik Rehber yazımıza bakabilirsiniz.
Ortam Değişkenleri
Lokalde .env dosyanız var, içinde DATABASE_URL, API_KEY falan tanımlı. Burada, vPS’e deploy ederken bu dosyayı kopyalamayı unutuyorsunuz — veya kopyalıyorsunuz. PM2 onu okuyamıyor çünkü çalışma dizini farklı. Klasik. Daha fazla bilgi için Flutter’da LLM Maliyeti Nasıl Kırılır: API’siz Yol yazımıza bakabilirsiniz.
PM2 ile uygulama başlatırken
--cwdparametresiyle çalışma dizinini açıkça belirtmek, ortam değişkeni sorunlarının büyük çoğunluğunu ortadan kaldırır.
Bellek Limitleri
Hmm, bir düşüneyim… Evet, bu da önemli. Lokalde 16 GB RAM’iniz var, VPS’de 1 GB. Node.js varsayılan heap limiti genelde 1.5-2 GB civarında, ama 1 GB RAM’li bir sunucuda swap da yoksa uygulama OOM (Out of Memory) killer tarafından öldürülebiliyor — hiç uyarı vermeden, log bırakmadan. PM2 loglarında “killed” görüyorsanız, büyük ihtimalle budur. Daha fazla bilgi için Windows 11’de Can Sıkıcı Yavaşlık Bitiyor mu? yazımıza bakabilirsiniz.
--max-memory-restart parametresiyle bellek limitini belirleyebilirsiniz. Örneğin: pm2 start app.js --max-memory-restart 512M. Bu, uygulamanız 512 MB’ı aştığında otomatik restart atar ve sunucunun tamamen kilitlenmesini önler.Pratik İpuçları: Deploy Öncesi Kontrol Listesi
Bu kadar acı deneyimden sonra kendime bir checklist oluşturdum. Her VPS deploy’ından önce şunları kontrol ediyorum — bazen sıkıcı geliyor. Sonradan “keşke bakmasaydım” demek istemiyorum:
node -vvenpm -vçıktılarını not alwhich nodeile hangi binary’nin kullanıldığını doğrula- PM2 kuruluysa
pm2 showile interpreter versiyonunu kontrol et .envdosyasının doğru dizinde ve okunabilir olduğunu teyit et- Sunucunun RAM ve disk durumunu
free -hvedf -hile kontrol et (bence en önemlisi) pm2 logsile ilk başlatmadaki hata mesajlarını incele
Bu listeyi uyguladığımdan beri — açık konuşayım — deploy sorunlarım en az %70 azaldı. Abartmıyorum. Önceden yarım günümü alan debug oturumları artık 15 dakikada çözülüyor. Küçük bir alışkanlık, koca bir fark. Daha fazla bilgi için Butterfly CSS: 2026’da Dikkat Çeken Hafif Bir Seçenek yazımıza bakabilirsiniz. Bu konuyla ilgili PDF Dünyasında Bir Nefes: Ücretsiz ve Limitsiz Araçlar yazımıza da göz atmanızı tavsiye ederim.
Durun, bir saniye.
Bak bir de şunu söyleyeyim: eğer kurumsal bir ortamda çalışıyorsanız,. Birden fazla geliştiricinin aynı sunucuya deploy ettiği bir yapınız varsa, Docker kullanmayı ciddi ciddi düşünün. Container içinde Node versiyonu, bağımlılıklar, ortam değişkenleri — her şey izole, her şey tanımlı, “bende çalışıyor. Sende çalışmıyor” diye bir dert kalmıyor. PM2 + NVM tuzağına düşme ihtimaliniz sıfıra iniyor. Küçük bir startup için VPS + PM2 gayet yeterli, ama ölçek büyüdükçe containerize etmek kaçınılmaz oluyor.
Bu konuyla bağlantılı olarak, terminal bazlı geliştirme araçlarını karşılaştırdığımız Claude Code, Codex CLI. Gemini CLI: 2026’nın En İyi AI Terminal Agent’ı Hangisi? yazımıza da göz atabilirsiniz — özellikle sunucu üzerinde hızlı debug yaparken bu araçlar bayağı işe yarıyor.
Garip gelecek ama, Bir de test otomasyonu tarafında, deploy sonrası her şeyin düzgün çalıştığını doğrulamak için Playwright ile Uçtan Uca Test: Tam Kapsamlı Rehber yazımız da ilginizi çekebilir.
Sıkça Sorulan Sorular
PM2 neden terminaldeki Node versiyonundan farklı bir versiyon kullanıyor?
PM2 global olarak kurulduğunda, o an aktif olan Node versiyonunun binary’sine bağlanıyor. Sonradan NVM ile farklı bir versiyona geçseniz bile, PM2’nin daemon’ı eski versiyonla çalışmaya devam ediyor. Bu yüzden pm2 update komutuyla daemon’ı yenilemek veya PM2’yi istenen versiyon altında yeniden kurmak gerekiyor.
PM2 ecosystem dosyasında interpreter yolu nasıl bulunur?
Terminalde which node veya nvm which current komutunu çalıştırarak aktif Node binary’sinin tam yolunu öğrenebilirsiniz. Bu yolu ecosystem.config.js dosyasındaki interpreter alanına yapıştırmanız yeterli. Genellikle /home/kullanici/.nvm/versions/node/vX.Y.Z/bin/node formatında olur.
NVM kullanmadan PM2 ile Node versiyonu sorunu yaşanır mı?
Daha az olasılıkla evet. Snap, apt veya manual derleme gibi farklı yöntemlerle birden fazla Node kurulumu yapılmışsa, PATH sıralamasına göre beklenmedik bir versiyon kullanılabilir. Bakın, ama en yaygın senaryo kesinlikle NVM kaynaklı oluyor.
Docker kullanırsam bu sorun ortadan kalkar mı?
Evet, büyük ölçüde kalkar. Docker container’ında Node versiyonu Dockerfile’da sabitlenir (mesela FROM node:18-alpine) ve container içindeki tüm süreçler bu versiyonu kullanır. PM2 kullanıyor olsanız bile, NVM’e gerek kalmaz ve versiyon uyumsuzluğu riski ortadan kalkar.
Bakın, burayı atlarsanız yazının kalanı anlamsız kalır.
PM2 restart ile PM2 update arasındaki fark nedir?
pm2 restart sadece uygulamayı yeniden başlatır ama aynı daemon. Aynı ortam değişkenleriyle çalışmaya devam eder. pm2 update ise PM2 daemon’ının kendisini yeniden başlatır ve güncel shell ortamını (yeni Node versiyonu dahil) almasını sağlar. Versiyon değişikliği yaptıysanız mutlaka pm2 update kullanmalısınız.
Kaynaklar ve İleri Okuma
PM2 Ecosystem File Dokümantasyonu
NVM GitHub — Önemli Notlar ve Bilinen Sorunlar
Bir şey dikkatimi çekti: Node.js Resmi Kurulum Rehberi (Package Manager ile)
Bu içerik işinize yaradı mı?
Benzer içerikleri kaçırmamak için beni sosyal medyada takip edin.



