DevOps

Vercel Deployment: Sıfırdan Zirveye En İyi Pratikler

Ahmet BulutAhmet Bulut
12 Ocak 2026
11 dk

Geçen Şubat'ta bir startup'ın CTO'su gece 11'de mesaj attı: "Production patladı, build pipeline her şeyi yiyor." Sorun karmaşık bir mimari değildi. vercel.json içinde yanlış bir rewrites kuralı, environment değişkeninin preview ortamına eklenmemesi ve bir DNS kaydının apex domain'e yanlış işaretlenmesi. Üç tane küçük şey, üç saatlik bir kriz. Vercel öğrenmesi kolay bir platform; ama doğru kullanılması başka bir konu.

Bu yazı, Vercel'e ilk defa vercel deployment yapacak geliştiriciler için yazıldı. Çoğu içeriğin atladığı detayları, ben kendi başıma birkaç gece uğraşarak öğrendim. Mantıklı olanı yazıyorum, geri kalanını siz uygulayacaksınız.

Vercel aslında ne çözüyor?

Vercel'i basit bir "Next.js host'u" olarak görmek yanlış. Asıl iş şu: kodunuzu Git'ten alıyor, build alıyor, statik içerikleri global bir CDN'e dağıtıyor, dinamik fonksiyonları edge veya serverless ortamlarda çalıştırıyor. Tüm bunları her PR için ayrı bir preview URL'iyle yapıyor. Yani siz bir frontend yazıyorsunuz, Vercel size bir CI/CD, bir CDN, bir serverless runtime ve bir staging environment'ı tek bir paket halinde veriyor.

Eskiden bu işler için Nginx ayarlamak, S3 + CloudFront kurmak, Lambda yazmak gerekiyordu. Bunların her biri ayrı bir uzmanlık. Vercel bu uzmanlığı bir git push komutuna indirgiyor. Tabii bedelsiz değil; bunu ileride konuşacağız.

Next.js dışında React, Vue, Svelte, SvelteKit, Astro, Nuxt, Remix, hatta saf statik HTML projeleri de çalışır. Vercel framework'ü otomatik tespit eder ve build komutunu kendi seçer. İstediğiniz zaman bu seçimi geçersiz kılabilirsiniz.

İlk on dakika: tek tıkla deploy

İlk projenizi açarken çoğu rehberin atladığı bir nokta var: önce repository'yi tertipli hale getirin. main branch'i kuralım, .gitignore dosyanız .env, node_modules, .next, dist içermeli. Vercel build sırasında node_modules'u repo'da görse build cache'i karışır.

vercel.com'da New Project butonuna basıp GitHub hesabınızı bağlayın. Repository listesinden seçim yapın, framework otomatik gelir. Burada acele etmeyin: Build & Output Settings kısmına bakın. Build komutu ve output directory doğru mu? Çoğu zaman doğru, ama monorepo kullanıyorsanız Root Directory'yi mutlaka ayarlamanız gerekir.

Bağladığınız ilk anda main branch'iniz production olur. Diğer her branch otomatik olarak preview deployment alır. Bu davranışı bilmek önemli; çünkü bir feature branch'e push attığınız anda, Vercel size https://<proje>-<hash>-<hesap>.vercel.app formatında bir URL üretir. Tasarımcıya, müşteriye, QA'ya bu URL'i atabilirsiniz. Aşağıda ekipler için neden faydalı olduğuna döneceğim.

vercel.json ile yapacaklarınız

Vercel'in büyük kısmı zero-config çalışır. Yani vercel.json dosyası olmadan da çalışır. Ama gerçek projelerde mutlaka birkaç şeyi tanımlamanız gerekir: redirects, rewrites, headers, fonksiyon bölge ayarı.

İşte sade ama gerçekçi bir örnek:

{
  "redirects": [
    { "source": "/eski-blog/:slug", "destination": "/blog/:slug", "permanent": true }
  ],
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        { "key": "X-Frame-Options", "value": "DENY" },
        { "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" }
      ]
    }
  ],
  "functions": {
    "app/api/*/.ts": { "maxDuration": 30, "memory": 1024 }
  }
}

Bu dosyayı yazarken sık yapılan hata: rewrites ve redirects'i karıştırmak. Redirect kullanıcının URL'ini değiştirir; rewrite arka planda farklı bir kaynağa yönlendirir, kullanıcı fark etmez. Bunu yanlış kullanmak SEO'nuzu çöker.

functions bölümünde maxDuration ve memory ayarları, özellikle Hobby planda kritik. Hobby'de fonksiyon süresi 10 saniyeyle sınırlı. Pro'ya geçtiğinizde 60 saniyeye, Enterprise'da 900 saniyeye çıkar. Bir API'niz dış servise istek atıyor ve cevap geç geliyorsa, maxDuration'ı bilinçli ayarlamak crash'leri engeller.

Render stratejisi: ISR, SSG, SSR, Edge

Frontend dünyasında en kafa karıştırıcı konu bu. Hangi sayfa nasıl render edilmeli? Genel mantığım şu: önce statik düşün, sonra ihtiyaç olduğunda dinamik yap.

Bir blog yazısı saatte bir güncelleniyor mu? SSG yeter, gerekirse ISR ile revalidate: 3600 ekleyin. Kullanıcının token'ına göre değişen bir dashboard mı var? SSR mecburi. Coğrafyaya göre değişen küçük bir kişiselleştirme mi yapıyorsunuz? Edge runtime düşünün. Ama uyarayım: Edge runtime tüm Node.js modüllerini desteklemez. Prisma'nın eski sürümleri, bcrypt, fs/path gibi şeyler edge'de patlar. Ben Edge'i sadece çok hızlı cevap gerektiren minik fonksiyonlar (auth check, geo redirect, A/B test) için kullanıyorum.

Bir gerçek: ISR herkesin sandığından daha güçlü. revalidate'i akıllıca kullanırsanız, neredeyse SSR kadar taze, neredeyse SSG kadar hızlı bir sonuç alırsınız. Yeni içerik yayınlandığında revalidatePath ile manuel temizleme de yapabilirsiniz. Pek çok pazarlama sitesi için doğru cevap budur.

SSR'a koşmadan önce kendinize sorun: "Bu sayfayı her istekte yeniden üretmem gerçekten gerekli mi?" Cevap çoğunlukla hayır.

Environment değişkenleri ve sırlar disiplini

Vercel'in environment yönetimi üç ayrı katmana bölünmüştür: Production, Preview, Development. Bu ayrımı atlamak büyük bir hata. Bir DATABASE_URL'i sadece Production'a eklerseniz, preview build'leri patlar. Sadece Preview'a eklerseniz, prod'da yoktur. Hangisinin nerede gerekli olduğunu yazılı tutun.

Pratikte ben şöyle çalışıyorum: Production veritabanı sadece Production environment'a, staging veritabanı Preview ve Development'a, üçüncü parti API anahtarları (Stripe, OpenAI, vs.) testnet/sandbox key olarak Preview'a, gerçek key Production'a.

Bir başka tuzak: NEXT_PUBLIC_ öneki olan değişkenler client'a gönderilir ve build sırasında bundle'a gömülür. Yani build aldıktan sonra değiştirseniz bile, eski değer client'taki kopyalarda kalır. NEXT_PUBLIC_ ile başlayan bir API anahtarı koymadan önce iki kere düşünün.

Sırlarınız büyüdükçe Vercel'in built-in env yönetimi yetmez. Bu noktada Doppler veya Infisical gibi araçlar devreye girer. Ama 5-10 değişkenli bir proje için Vercel'in kendi paneli fazlasıyla yeterli.

Domain ve DNS'in ince noktaları

Domain bağlamak iki dakikalık iş gibi görünür. Genellikle değildir. Vercel size cname.vercel-dns.com hedefini verir. Apex domain için (yani poitim.com) A kaydı olarak 76.76.21.21, www için CNAME. DNS sağlayıcınız ALIAS veya ANAME destekliyorsa apex'te de CNAME mantığı kullanabilirsiniz; Cloudflare bunu "flatten" eder.

İlk hata: TTL'i 24 saat bırakmak. Yeni bir domain bağlarken TTL'i 300 saniyeye düşürün, propagasyon hızlansın. Sonra geri kaldırırsınız.

İkinci hata: www ve apex arasındaki redirect'i tanımlamamak. www.poitim.com'u apex'e (veya tam tersi) 308 redirect ile yönlendirin. Aksi halde Google iki ayrı site sanır, SEO bölünür.

Üçüncüsü, ki bana en az iki kez başıma geldi: SSL sertifikası 24 saatte gelmiyorsa DNS kayıtlarınızı tekrar kontrol edin. Vercel sertifikayı ancak doğru DNS'i gördükten sonra üretir.

Ekipler ve preview workflow'u

Tek başına çalışırken preview URL'leri lüks görünür. Ekiple çalışırken kritik. Tasarımcı her PR için yeni bir URL alıyor, QA o URL'de test ediyor, müşteri onayını o URL üzerinden veriyor. Bu üç aşamanın koordinasyonu ekipler için ayrı bir iş.

Burada şunu söylemek istiyorum: deployment workflow'unu Slack mesajlarıyla yönetmeyin. Hangi PR hangi preview URL'ine bağlı, hangi feature hangi sprint'e ait, kimin onayı bekleniyor; bu bilgilerin yaşadığı bir yer olsun. Bizim proje yönetimi modülümüz tam olarak bu noktaya hitap ediyor: deployment task'ları, preview URL'leri ve onay zincirini tek bir board üzerinde toplayabiliyorsunuz. Task yönetimi tarafında da deploy öncesi checklist'leri tutmak işe yarar.

Saatlerce uğraştıran hatalar

Vercel'de bana en çok zaman kaybettiren şeyleri sıralıyorum, ama "5 hata" listesi olarak değil. Çoğu birbiriyle bağlantılı.

Build cache'in eski kalması en sinir bozucu olanı. Yeni bir paket eklediniz, build geçti, deploy oldu, ama eski versiyon çalışıyor. Vercel dashboard'daki Deployments sekmesinden "Redeploy" derken "Use existing Build Cache" seçeneğini kapatmanız gerekir. Bu kutucuk varsayılan açık geliyor; yeni başlayan herkes en az bir kez yakalanır.

İkinci klasik: monorepo'da Root Directory'yi yanlış set etmek. apps/web altındaki Next.js'iniz var ama Vercel kök dizinden build almaya çalışıyor. Build hata vermeden geçer, ama deploy edilen şey yanlış proje. Project Settings > General > Root Directory'yi düzeltin.

Üçüncüsü: Serverless function size limiti. Hobby'de 50 MB, Pro'da 250 MB sıkıştırılmış. Prisma client + büyük bağımlılıklar bu limiti aşar. Çözüm next.config.js içinde serverComponentsExternalPackages kullanmak veya bağımlılıkları temizlemek. Sentry'nin source map upload'ını yanlış konfigüre ederseniz function bundle'ı şişer; dikkat edin.

Dördüncü, daha sinsi bir tane: timezone. Vercel fonksiyonları UTC'de çalışır. new Date() ile localtime beklerseniz canlıda yanlış sonuç alırsınız. Tarih hesaplarınızı her zaman UTC bazlı yapın, render anında client'ın timezone'una çevirin.

İzleme, gözlem ve sonraki adım

Deploy aldınız, çalışıyor. İyi. Ama production'da bir şey patlarsa nasıl haber alacaksınız? Vercel Analytics ücretsiz planında temel istatistikleri verir. Daha derin görünürlük için Sentry, Axiom veya LogDNA bağlamak gerekir. Function logları Vercel dashboard'unda 1 saat tutulur, sonra silinir; uzun vadeli debug için bir log servisine yönlendirin.

Bir öneri: ilk deploy'dan hemen sonra bir uptime monitor kurun. UptimeRobot, BetterStack, Checkly... ne olursa olsun bir tane. Vercel'in kendi durumu nadiren çöker; ama sizin bağımlı olduğunuz bir API çökerse Vercel bunu bilmez.

Vercel'i hakkıyla kullanmak, dokümanı okumakla başlar ama dokümanın söylemediği şeyleri öğrenmek için birkaç gece uğraşmak gerekir. Bu yazı o gecelerden birkaçının özeti. Eğer takım olarak deployment süreçlerinizi düzene koymak istiyorsanız, Poitim'in canlı demosunu deneyebilir veya ekip yönetimi özelliklerine göz atabilirsiniz. Sonraki canlı yayınınızda görüşürüz.

Sık Sorulan Sorular

Vercel Deployment: Sıfırdan Zirveye En İyi Pratikler