İçeriğe atla

2025-09-30

Vercel Alternatifleri: Next.js Deployment Kapsamlı Rehberi

Vercel dışında Next.js uygulamalarını deploy etmenin kapsamlı rehberi - production ortamları için maliyet analizi, implementasyon detayları ve migration stratejileri

Hiç bir side project’in faturasına bakıp Netflix aboneliğinden daha pahalıya geldiğini görüp şaşırdınız mı? Ya da Next.js uygulamanız için deployment seçeneklerini değerlendirirken Vercel’in platformunun ötesinde bir hayat olup olmadığını merak ettiniz mi? Production migration’ları ve deployment optimizasyonlarıyla çalışmak bana alternatiflerin uygulanabilir olduğunu ve belirli use case’ler için sıklıkla daha üstün olduğunu öğretti.

Next.js uygulamalarını Vercel olmadan deploy etme konusunda keşfettiklerimi, dokümantasyonda kimsenin bahsetmediği gotcha’ları ve production’da karşılaşacağınız maliyetleri paylaşayım.

Bağlam - Ekipler Neden Vercel’in Ötesini Araştırıyor

Next.js uygulamalarıyla çalışmak bana Vercel’in mükemmel bir geliştirici deneyimi sunduğunu, ancak birkaç faktörün ekipleri alternatifleri keşfetmeye yönlendirdiğini öğretti:

  1. Vendor Lock-in Endişeleri: Vercel’in platforma özel API’leri ve deployment pattern’leri gelecekteki migration’ları zorlaştıran bağımlılıklar yaratıyor. Ekipler kendilerini diğer platformlara tercüme edilemeyen proprietary özelliklere bağlı buluyor.

  2. Tek Nokta Bağımlılığı: Kritik altyapı için tek bir vendor’a güvenmek risk yaratıyor. Vercel kesinti yaşadığında veya fiyatlandırma modelini değiştirdiğinde, ekiplerin sınırlı seçenekleri oluyor.

  3. Ölçekte Maliyet: Platform, dahil edilen kotanın ötesinde terabayt başına 150u¨cretalıyor(fazlakullanımdaGBbas\cına150 ücret alıyor (fazla kullanımda GB başına 0.15), ve function invocation’lar hızla birikebiliyor. Marketing kampanyalarının normal trafiğin 10 katını getirdiği durumlar gözlemledim ve function invocation limitlerinin tam da dönüşüm potansiyelinin en yüksek olduğu anda ortaya çıktığını gördüm - bu pattern, ölçekleme etkinliklerinden önce platform limitlerini anlamanın önemini vurguluyor.

Kararı etkileyen ek faktörler:

  • Belirli bölgesel uyumluluk veya veri yerleşimi ihtiyacı
  • Mevcut cloud altyapı yatırımlarından yararlanma arzusu
  • Özel caching kuralları veya deployment yapılandırması gereksinimleri
  • Vercel’in fiyatlandırma kademelerine uymayan bütçe kısıtlamaları

Analiz Framework’ü - Deployment Seçeneklerini Değerlendirme

Belirli platformlara dalmadan önce, Next.js deployment seçeneklerini değerlendirmek için kullandığım framework:

Deployment Gereksinimleri

Feature Destegi

Maliyet Yapisi

Performans Ihtiyaclari

Ekip Yetenekleri

SSR/ISR Destegi

API Routes

Middleware

Image Optimization

Sabit vs Kullanim

Bandwidth Maliyetleri

Compute Fiyatlandirma

Global Dagitim

Cold Start Sureleri

Cache Stratejisi

DevOps Deneyimi

Bakim Kapasitesi

Platform Asinaligi

Yönetilen Platform Alternatifleri

AWS Amplify - Enterprise-Ready Seçim

AWS Amplify, Next.js deployment’ları için önemli ölçüde olgunlaştı. İşte bir production yapılandırması:

# amplify.yml
version: 1
frontend:
  phases:
    preBuild:
      commands:
        - npm ci --cache .npm --prefer-offline
        # Sharp/image optimization için fix
        - npm install --os=linux --cpu=x64 sharp
    build:
      commands:
        - npm run build
  artifacts:
    baseDirectory: .next
    files:
      - '**/*'
  cache:
    paths:
      - .npm/**/*
      - node_modules/**/*

# Özel cache yapılandırması
customHeaders:
  - pattern: '**/*'
    headers:
      - key: 'Cache-Control'
        value: 'public, max-age=31536000, immutable'
  - pattern: '**/*.html'
    headers:
      - key: 'Cache-Control'
        value: 'public, max-age=0, must-revalidate'

Önemli Uygulama Detayları:

  • Build dakikaları her biri $0.01 (tipik build’ler: 2-4 dakika)
  • Bandwidth fiyatlandırması: 15GB ücretsiz katmandan sonra $0.15/GB
  • Çok sayıda redirect destekler, ancak binlerce kural ile konsol performansı düşüyor
  • Pull request’ler için otomatik branch deployment’ları

Gerçek Dünya Gotcha’sı: Redirect konsol performans sorunu dokümante edilmemiş. Bu, 2.000+ redirect’li eski uygulamaları migrate ederken belirgin hale geliyor. Çözüm? Redirect’leri middleware kullanarak uygulama seviyesinde gerçekleştirmek:

// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

// Redirect'leri JSON dosyasından veya veritabanından yükle
import redirects from './redirects.json';

export function middleware(request: NextRequest) {
  const pathname = request.nextUrl.pathname;

  // Pathname'in redirect'e ihtiyacı var mı kontrol et
  const redirect = redirects[pathname];
  if (redirect) {
    return NextResponse.redirect(
      new URL(redirect.destination, request.url),
      redirect.permanent ? 308 : 307
    );
  }

  return NextResponse.next();
}

export const config = {
  matcher: '/((?!api|_next/static|_next/image|favicon.ico).*)',
};

Cloudflare Pages - Uygun Maliyetli Güç Merkezi

OpenNext adapter’ıyla Cloudflare Pages şaşırtıcı derecede yetenekli hale geldi. Uygulama için iki yaklaşım var:

Seçenek 1: Sadece Edge Runtime (Sınırlı ama Hızlı)

npm install @cloudflare/next-on-pages

Seçenek 2: Tam Node.js Desteği (Önerilen)

npm install @opennextjs/cloudflare

OpenNext kullanarak production-ready yapılandırma:

// next.config.js
const { withOpenNextConfig } = require('@opennextjs/cloudflare/next-config');

const nextConfig = {
  output: 'standalone',
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: '**.cloudinary.com',
      },
    ],
  },
  experimental: {
    // Belirli route'lar için edge runtime'ı etkinleştir
    runtime: 'edge',
  },
};

module.exports = withOpenNextConfig(nextConfig);
# wrangler.toml
name = "nextjs-production"
compatibility_date = "2024-01-01"
compatibility_flags = ["nodejs_compat"]

[site]
bucket = "./.vercel/output/static"

[env.production]
vars = { ENVIRONMENT = "production" }

[[d1_databases]]
binding = "DB"
database_name = "production"
database_id = "your-database-id"

[[kv_namespaces]]
binding = "CACHE"
id = "your-kv-namespace-id"

Maliyet Analizi:

  • Bandwidth: Sınırsız (pazarlama konuşması değil)
  • Request’ler: Günde 100.000 ücretsiz, sonra milyon başına $0.50
  • Workers: Günde 100.000 request ücretsiz
  • Çoğu uygulama için toplam aylık maliyet: $0

Netlify - Geliştirici Dostu Orta Yol

Netlify’ın Next.js desteği önemli ölçüde gelişti. Karmaşık gereksinimleri ele alan bir yapılandırma:

# netlify.toml
[build]
  command = "npm run build"
  publish = ".next"

[[plugins]]
  package = "@netlify/plugin-nextjs"

[build.environment]
  NEXT_USE_NETLIFY_EDGE = "true"
  NETLIFY_NEXT_PLUGIN_SKIP = "false"

# API route'lar için function yapılandırması
[functions]
  directory = "netlify/functions"
  included_files = ["data/**"]

# Splat destekli redirect kuralları
[[redirects]]
  from = "/old-blog/*"
  to = "/posts/:splat"
  status = 301
  force = true

# Güvenlik için özel header'lar
[[headers]]
  for = "/*"
  [headers.values]
    X-Frame-Options = "DENY"
    X-Content-Type-Options = "nosniff"
    X-XSS-Protection = "1; mode=block"

Pro İpucu: Netlify’ın form handling ve split testing özellikleri Next.js ile sorunsuz çalışır, bu diğer platformlarda ek kurulum gerektirir.

Self-Hosting Çözümleri - Maksimum Kontrol

AWS’de SST - Serverless Doğru Yapılmış

SST (eskiden Serverless Stack), Next.js için en iyi serverless deployment deneyimini sağlar. Tam bir production kurulumu:

// sst.config.ts
import { SSTConfig } from "sst";
import { NextjsSite, Bucket, Table } from "sst/constructs";

export default {
  config(_input) {
    return {
      name: "nextjs-production",
      region: "us-east-1",
    };
  },
  stacks(app) {
    app.stack(function Site({ stack }) {
      // Session storage için DynamoDB
      const table = new Table(stack, "sessions", {
        fields: {
          sessionId: "string",
        },
        primaryIndex: { partitionKey: "sessionId" },
      });

      // Upload'lar için S3
      const bucket = new Bucket(stack, "uploads", {
        cors: [
          {
            maxAge: "1 day",
            allowedOrigins: ["*"],
            allowedHeaders: ["*"],
            allowedMethods: ["GET", "PUT", "POST", "DELETE", "HEAD"],
          },
        ],
      });

      // Next.js sitesi
      const site = new NextjsSite(stack, "site", {
        customDomain: {
          domainName: "example.com",
          hostedZone: "example.com",
        },
        environment: {
          DATABASE_URL: process.env.DATABASE_URL,
          SESSION_TABLE_NAME: table.tableName,
          UPLOAD_BUCKET_NAME: bucket.bucketName,
        },
        bind: [table, bucket],
        // Performans optimizasyonları
        memorySize: 1024,
        timeout: "30 seconds",
        // Bölgesel yapılandırma
        regional: {
          enableServerUrlIamAuth: true,
        },
      });

      stack.addOutputs({
        SiteUrl: site.url,
        CloudFrontUrl: site.cdk.distribution.distributionDomainName,
      });
    });
  },
} satisfies SSTConfig;

Ayda 1M request için maliyet dağılımı:

  • Lambda: ~$20 (free tier dahil)
  • CloudFront: Bandwidth için ~$10
  • S3: Storage için ~$1
  • Toplam: ~31/ay(benzertrafikic\cinVercelde31/ay (benzer trafik için Vercel'de 320)

Docker + VPS - Bütçe Şampiyonu

Sunucu yönetiminde rahat olan ekipler için, Hetzner veya DigitalOcean’da self-hosting rakipsiz değer sağlar. Production-grade Docker kurulumu:

# Dockerfile
# Dependencies
FROM node:20-alpine AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app

# Lockfile'a göre dependency'leri yükle
COPY package.json package-lock.json* ./
RUN \
  if [ -f package-lock.json ]; then npm ci --omit=dev; \
  else echo "Lockfile bulunamadı." && exit 1; \
  fi

# Builder
FROM node:20-alpine AS builder
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .

# Uygulamayı build et
ENV NEXT_TELEMETRY_DISABLED 1
RUN npm run build

# Runner
FROM node:20-alpine AS runner
WORKDIR /app

ENV NODE_ENV production
ENV NEXT_TELEMETRY_DISABLED 1

# Non-root kullanıcı oluştur
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

# Build edilmiş uygulamayı kopyala
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static

USER nextjs
EXPOSE 3000
ENV PORT 3000

CMD ["node", "server.js"]
# docker-compose.yml
version: '3.8'

services:
  nextjs:
    build: .
    restart: unless-stopped
    environment:
      - NODE_ENV=production
      - DATABASE_URL=${DATABASE_URL}
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/api/health"]
      interval: 30s
      timeout: 10s
      retries: 3
    networks:
      - app-network

  nginx:
    image: nginx:alpine
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/ssl:/etc/nginx/ssl:ro
      - ./nginx/cache:/var/cache/nginx
    depends_on:
      - nextjs
    networks:
      - app-network

  # Opsiyonel: Caching için Redis
  redis:
    image: redis:alpine
    restart: unless-stopped
    command: redis-server --appendonly yes
    volumes:
      - redis-data:/data
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

volumes:
  redis-data:

Production için Nginx Yapılandırması:

# nginx.conf
upstream nextjs {
    server nextjs:3000;
}

server {
    listen 80;
    server_name example.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com;

    ssl_certificate /etc/nginx/ssl/cert.pem;
    ssl_certificate_key /etc/nginx/ssl/key.pem;

    # Güvenlik header'ları
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;

    # Statik asset'leri cache'le
    location /_next/static {
        proxy_pass http://nextjs;
        proxy_cache_valid 365d;
        add_header Cache-Control "public, immutable";
    }

    # Image'leri cache'le
    location /_next/image {
        proxy_pass http://nextjs;
        proxy_cache_valid 365d;
        add_header Cache-Control "public, max-age=31536000, immutable";
    }

    # Geri kalan her şey
    location / {
        proxy_pass http://nextjs;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Platform-as-a-Service - Coolify ve Alternatifler

Coolify, Vercel’e güçlü bir self-hosted alternatif olarak ortaya çıktı. Temiz bir VPS’e kurulum:

# Ubuntu/Debian'a Coolify kurulumu
curl -fsSL https://coolify.io/install.sh | bash

# Veya doğrudan Docker kullanarak
docker run --rm -it \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v coolify:/data \
  -e COOLIFY_APP_ID=your-app-id \
  -p 8000:80 \
  -p 8443:443 \
  -p 3000:3000 \
  coolify/coolify:latest

Next.js için Coolify Yapılandırması:

# coolify.yaml
name: nextjs-app
type: node
port: 3000
build:
  command: npm run build
  install: npm ci
start:
  command: npm start
env:
  NODE_ENV: production
  DATABASE_URL: ${DATABASE_URL}
health:
  path: /api/health
  interval: 30
resources:
  limits:
    memory: 1Gi
    cpu: 1000m
  requests:
    memory: 512Mi
    cpu: 500m

Gerçek Dünya Maliyet Karşılaştırması

Production deployment’larına dayanarak, aylık olarak ne ödemeyi bekleyebilirsiniz:

Note: Bu maliyetler, orta düzeyde compute gereksinimleriyle ayda yaklaşık 500GB bandwidth sunan uygulamalara dayanıyor.

PlatformKüçük Uygulama (10GB/ay)Orta Uygulama (500GB/ay)Büyük Uygulama (2TB/ay)Notlar
Vercel$20$80$320Tahmin edilebilir ama ölçekte pahalı
Netlify$0 (free tier)$20$95+Vercel’den daha iyi tahmin edilebilirlik
Cloudflare Pages$0$0$0Sınırsız bandwidth
AWS Amplify~$5~$30~$70Kullandıkça öde modeli
Hetzner + CloudflareEUR3.79EUR3.79EUR3.79Trafikten bağımsız sabit maliyet
AWS’de SST~$10~$20-40~$50-100Kullanım paternlerine göre değişir
DigitalOcean Apps$5$25$100Basit fiyatlandırma yapısı

Migration Stratejisi - Hafta Hafta Yaklaşım

Hafta 1 - Değerlendirme ve Planlama

Mevcut Vercel kullanımınızı analiz ederek başlayın:

// scripts/analyze-vercel-usage.js
const { VercelClient } = require('@vercel/client');

async function analyzeUsage() {
  const client = new VercelClient({ token: process.env.VERCEL_TOKEN });

  // Bandwidth kullanımını al
  const bandwidth = await client.get('/v1/usage/bandwidth');

  // Function kullanımını al
  const functions = await client.get('/v1/usage/functions');

  // Build dakikalarını al
  const builds = await client.get('/v1/usage/builds');

  console.log({
    monthlyBandwidth: bandwidth.total,
    functionInvocations: functions.total,
    buildMinutes: builds.total,
    estimatedCost: calculateCost(bandwidth, functions, builds)
  });
}

function calculateCost(bandwidth, functions, builds) {
  // Vercel fiyatlandırma hesaplamasını uygula
  // Bu baseline maliyetlerinizi anlamanıza yardımcı olur
}

Hafta 2 - Proof of Concept

Seçtiğiniz platforma minimal bir versiyon deploy edin:

# Örnek: Cloudflare Pages deployment'ını test etme
npx create-next-app@latest test-deployment
cd test-deployment

# OpenNext adapter'ı ekle
npm install @opennextjs/cloudflare

# Yapılandır ve deploy et
npx wrangler pages deploy .next

Hafta 3 - Production Hazırlığı

Monitoring ve observability’yi uygulayın:

// lib/monitoring.ts
import { metrics } from '@opentelemetry/api-metrics';

const meter = metrics.getMeter('nextjs-app', '1.0.0');

// Özel metrikler oluştur
const requestDuration = meter.createHistogram('http_request_duration', {
  description: 'HTTP request süresi milisaniye cinsinden',
  unit: 'ms',
});

const deploymentCost = meter.createGauge('deployment_cost', {
  description: 'Tahmini deployment maliyeti USD cinsinden',
  unit: 'USD',
});

export function trackRequest(route: string, duration: number) {
  requestDuration.record(duration, { route });
}

export function updateCost(platform: string, cost: number) {
  deploymentCost.record(cost, { platform });
}

Hafta 4 - Migration ve Doğrulama

Rollback stratejisiyle migration’ı gerçekleştirin:

# .github/workflows/deploy-with-rollback.yml
name: Deploy with Rollback

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Mevcut deployment'ı yedekle
        run: |
          # Rollback için mevcut deployment bilgisini kaydet
          echo ${{ github.sha }} > .last-known-good

      - name: Yeni platforma deploy et
        run: |
          # Deployment komutlarınız burada
          npm run deploy:production

      - name: Health check
        id: health
        run: |
          # Deployment'ın sağlıklı olduğunu doğrula
          curl -f https://your-app.com/api/health || exit 1

      - name: Başarısızlıkta rollback
        if: failure()
        run: |
          # Önceki versiyona geri dön
          LAST_GOOD=$(cat .last-known-good)
          npm run deploy:rollback $LAST_GOOD

Yaygın Tuzaklar ve Çözümler

Sharp/Image Optimization Zorluğu

Neredeyse her platform Next.js image optimization ile zorlanıyor. Evrensel çözüm:

// next.config.js
module.exports = {
  images: {
    loader: 'custom',
    loaderFile: './lib/image-loader.js',
  },
};

// lib/image-loader.js
export default function cloudinaryLoader({ src, width, quality }) {
  const params = ['f_auto', 'c_limit', `w_${width}`, `q_${quality || 'auto'}`];
  const paramsString = params.join(',');
  return `https://res.cloudinary.com/your-cloud-name/image/upload/${paramsString}/${src}`;
}

Environment Variable Yönetimi

Farklı platformlar environment variable’ları farklı şekilde ele alır. Birleşik bir yaklaşım:

// lib/config.ts
interface Config {
  database: {
    url: string;
    poolSize: number;
  };
  redis: {
    url: string;
  };
  platform: 'vercel' | 'amplify' | 'cloudflare' | 'self-hosted';
}

function detectPlatform(): Config['platform'] {
  if (process.env.VERCEL) return 'vercel';
  if (process.env.AWS_REGION) return 'amplify';
  if (process.env.CF_PAGES) return 'cloudflare';
  return 'self-hosted';
}

export const config: Config = {
  database: {
    url: process.env.DATABASE_URL!,
    poolSize: detectPlatform() === 'self-hosted' ? 20 : 1,
  },
  redis: {
    url: process.env.REDIS_URL || 'redis://localhost:6379',
  },
  platform: detectPlatform(),
};

ISR Cache Davranış Farklılıkları

Incremental Static Regeneration platformlar arasında farklı davranır:

// pages/api/revalidate.ts
import { NextApiRequest, NextApiResponse } from 'next';

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  const { path, platform } = req.query;

  try {
    switch (platform) {
      case 'vercel':
        await res.revalidate(path as string);
        break;

      case 'cloudflare':
        // Cloudflare KV-tabanlı revalidation
        await fetch(`https://api.cloudflare.com/client/v4/zones/${process.env.CF_ZONE}/purge_cache`, {
          method: 'POST',
          headers: {
            'Authorization': `Bearer ${process.env.CF_TOKEN}`,
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            files: [`https://example.com${path}`],
          }),
        });
        break;

      case 'aws':
        // CloudFront invalidation
        const cloudfront = new AWS.CloudFront();
        await cloudfront.createInvalidation({
          DistributionId: process.env.CF_DISTRIBUTION_ID,
          InvalidationBatch: {
            CallerReference: Date.now().toString(),
            Paths: {
              Quantity: 1,
              Items: [path as string],
            },
          },
        }).promise();
        break;
    }

    res.status(200).json({ revalidated: true });
  } catch (err) {
    res.status(500).json({ error: 'Revalidation başarısız' });
  }
}

Performans Karşılaştırması - Gerçek Dünya Metrikleri

Birden fazla production uygulamasını migrate ettikten sonra, gözlemlenen performans metrikleri:

Note: Bu metrikler, karışık statik ve dinamik içerikle saniyede 100-500 request sunan uygulamalardan alınmıştır.

Time to First Byte (TTFB):

  • Vercel: 45-60ms (global ortalama)
  • Cloudflare Pages: 25-40ms (sınıfının en iyisi)
  • CloudFront ile AWS: 50-80ms
  • Cloudflare ile self-hosted: 60-100ms
  • Doğrudan VPS (CDN yok): 100-300ms

Cold Start Süreleri:

  • Vercel Functions: 100-300ms
  • AWS Lambda (SST): 400-800ms
  • Cloudflare Workers: 0-500ms (“sıfır cold start” olarak pazarlanıyor ama kullanıcılar pratikte 100-500ms rapor ediyor)
  • Container-tabanlı: 0ms (her zaman sıcak)

Build Süreleri:

  • Vercel: 2-3 dakika
  • Netlify: 3-4 dakika
  • AWS Amplify: 3-5 dakika
  • GitHub Actions’dan VPS’e: 1-2 dakika

Use Case’e Göre Öneriler

Startup’lar ve MVP’ler için

Öneri: OpenNext ile Cloudflare Pages

  • Sıfır bandwidth maliyeti büyük bir ölçekleme endişesini ortadan kaldırır
  • Free tier çoğu startup trafiğini karşılar
  • Kutudan çıkan global performans

Enterprise Uygulamalar için

Öneri: AWS’de SST

  • Tam AWS servis entegrasyonu
  • Uyumluluk için infrastructure as code
  • Reserved capacity ile tahmin edilebilir maliyetler

Yüksek Trafikli İçerik Siteleri için

Öneri: Cloudflare CDN ile self-hosted

  • Trafikten bağımsız sabit aylık maliyetler
  • Caching stratejisi üzerinde tam kontrol
  • Vendor lock-in yok

Ajanslar ve Freelancer’lar için

Öneri: Hetzner’da Coolify

  • Bir VPS’te sınırsız müşteri projesi barındırın
  • Müşteriler için basit deployment arayüzü
  • Sunucu başına EUR3.79/ay ile uygun maliyetli

Bugün Farklı Ne Yapardım

Çeşitli migration’lara bakarak, öğrendiklerim:

OpenNext Uyumluluğu ile Başlayın: Uygulamanızı ilk günden OpenNext ile çalışacak şekilde tasarlayın. Bu, kod değişikliği olmadan platform geçişleri için maksimum esneklik sağlar.

Platform-Agnostic Monitoring Uygulayın: Platform-specific çözümler yerine OpenTelemetry veya benzer vendor-neutral observability araçlarını kullanın. Bu, migration’ları çok daha sorunsuz hale getirir.

Maliyet Takibini Erken Oluşturun: Baştan itibaren maliyet takibi uygulayın:

// lib/cost-tracker.ts
class DeploymentCostTracker {
  private costs: Map<string, number> = new Map();

  track(service: string, amount: number) {
    const current = this.costs.get(service) || 0;
    this.costs.set(service, current + amount);
  }

  async reportDaily() {
    const total = Array.from(this.costs.values()).reduce((a, b) => a + b, 0);

    // Monitoring servisine gönder
    await fetch('/api/metrics', {
      method: 'POST',
      body: JSON.stringify({
        date: new Date().toISOString(),
        costs: Object.fromEntries(this.costs),
        total,
      }),
    });

    // Sonraki gün için sıfırla
    this.costs.clear();
  }
}

Multi-Platform Deployment için Tasarlayın: Birden fazla platform için deployment yapılandırmalarını koruyun. Bu, vendor’larla pazarlık gücü ve hızlı disaster recovery seçenekleri sağlar.

Önemli Çıkarımlar

Sayısız Next.js uygulamasını Vercel’den migrate ettikten sonra, tutarlı olarak doğru olan şeyler:

  1. Alternatifler production-ready. OpenNext ve geliştirilmiş platform desteği sayesinde artık her büyük Next.js özelliği alternatif platformlarda çalışıyor.

  2. Maliyet tasarrufları önemli olabilir. Ekipler sıklıkla performansı koruyarak veya geliştirirken aylık deployment maliyetlerini %70-90 azaltıyor.

  3. Platform lock-in önlenebilir. Doğru mimari kararlarıyla, platform değiştirmek haftalar değil, günler içinde gerçekleştirilebilir.

  4. Self-hosting hiç olmadığı kadar erişilebilir. Coolify ve Dokploy gibi araçlar, bir zamanlar önemli DevOps uzmanlığı gerektiren şeyleri demokratikleştirdi.

  5. Evrensel en iyi seçim yok. Özel gereksinimleriniz - trafik paternleri, ekip uzmanlığı, bütçe kısıtlamaları - kararı yönlendirmeli.

Next.js deployment manzarası dramatik olarak gelişti. Vercel mükemmel bir platform olmaya devam ediyor, ancak artık production deployment’ları için tek uygulanabilir seçenek değil. İster maliyetleri optimize ediyor, ister daha fazla kontrol arıyor, ister mevcut altyapıyla uyum sağlıyor olun, muhtemelen ihtiyaçlarınıza daha iyi uyan bir deployment stratejisi vardır.

Popüler olana göre değil, gereksinimlerinize göre seçin. Ve unutmayın - OpenNext ve modern deployment araçlarıyla, her zaman daha sonra fikrinizi değiştirebilirsiniz.

İlgili yazılar