Skip to content
~/sph.sh

AWS ile Edge Computing: CloudFront Functions vs Lambda@Edge

Global uygulamalar için AWS edge computing çözümlerini seçme ve uygulama üzerine pratik örnekler ve maliyet optimizasyonu stratejileri içeren kapsamlı teknik rehber.

Edge computing, kod yürütmeyi merkezi data center'lardan kullanıcılara yakın konumlara taşıyor. AWS CloudFront dünya çapında 1600+ edge location ile çalışıyor ve iki farklı edge computing çözümü sunuyor: CloudFront Functions ve Lambda@Edge. Her iki servis ile çalışmak bana doğru seçimin maliyet, performans ve implementasyon karmaşıklığı üzerinde önemli etkisi olduğunu öğretti.

AWS ile edge computing çözümleri geliştirirken öğrendiklerim.

CloudFront Edge Computing'i Anlamak

CloudFront ile edge computing, kodu kullanıcılara yakın edge location'larda çalıştırarak yürütmeyi mümkün kılıyor. Her iki servis de request'leri edge'de işleyerek latency sorunlarını çözüyor, ancak farklı kullanım senaryolarına hitap ediyorlar.

CloudFront Functions, cache key normalizasyonu ve header manipülasyonu gibi yüksek hacimli, basit dönüşümlerde Lambda@Edge'e göre 1/6 maliyetle mükemmel çalışıyor. Lambda@Edge ise network erişimi, harici API'ler veya karmaşık business logic gerektiren operasyonları ele alıyor.

Execution Point'leri

CloudFront, edge function'ların çalışabileceği dört execution point sağlıyor:

  • Viewer Request: CloudFront request'i aldıktan sonra, cache'i kontrol etmeden önce
  • Viewer Response: Viewer'a response dönmeden önce
  • Origin Request: Origin'e forward etmeden önce (sadece cache miss) - Sadece Lambda@Edge
  • Origin Response: Origin'den response alındıktan sonra - Sadece Lambda@Edge

Servis Karşılaştırması: Doğru Seçimi Yapmak

CloudFront Functions ve Lambda@Edge arasındaki farkları anlamak, maliyet-etkin mimari kararlar almak için önemli.

Özellik Karşılaştırması

ÖzellikCloudFront FunctionsLambda@Edge
Execution Location1600+ edge location1600+ edge location
RuntimeSadece JavaScriptNode.js 22.x, Python 3.13
Execution Time< 1 milisaniye5s (viewer), 30s (origin)
Memory2 MB128 MB - 10 GB
Max Package Size10 KB1 MB (viewer), 50 MB (origin)
Network AccessHayırEvet
Event Type'larıViewer request/responseTüm 4 event type
Request Body AccessHayırEvet (origin event'lerde)
Response Size40 KB1 MB
Fiyatlandırma (1M başına)$0.10 invocation$0.60 invocation + compute
Cold StartYok1-3 saniye
KeyValueStoreEvetHayır

Maliyet Etkisi

Aylık 10 milyar request için maliyet farkı önemli:

  • CloudFront Functions: 10,000M × 0.10=0.10 = 1,000
  • Lambda@Edge: 10,000M × 0.60+compute=0.60 + compute = 6,000-$8,000

CloudFront Functions basit kullanım senaryolarında 5-8x daha ucuz.

Karar Çerçevesi

CloudFront Functions: Hız İçin Optimize

CloudFront Functions tüm 1600+ edge location'da sub-milisaniye latency ile çalışıyor. Network erişimi gerektirmeyen yüksek hacimli, basit operasyonlar için ideal.

Kullanım Senaryosu 1: Cache Key Normalizasyonu

Query parameter'ları normalize ederek cache hit ratio'yu optimize etmek, origin load'u önemli ölçüde azaltabilir.

javascript
// Cache key normalizasyonu için CloudFront Functionfunction handler(event) {    var request = event.request;    var querystring = request.querystring;
    // Device indicator'larını standart formata normalize et    if (querystring.device) {        var deviceValue = querystring.device.value.toLowerCase();        if (deviceValue === 'm' || deviceValue === 'mobile') {            querystring.device.value = 'mobile';        } else if (deviceValue === 'd' || deviceValue === 'desktop') {            querystring.device.value = 'desktop';        }    }
    // Query parameter'ları alfabetik sırala - tutarlı cache key için    var sortedQuerystring = {};    Object.keys(querystring)        .sort()        .forEach(function(key) {            sortedQuerystring[key] = querystring[key];        });
    request.querystring = sortedQuerystring;
    // Accept-Encoding header'ını normalize et    if (request.headers['accept-encoding']) {        var acceptEncoding = request.headers['accept-encoding'].value;        if (acceptEncoding.includes('br')) {            request.headers['accept-encoding'].value = 'br,gzip';        } else if (acceptEncoding.includes('gzip')) {            request.headers['accept-encoding'].value = 'gzip';        }    }
    return request;}

Bu normalizasyon production sistemde cache hit ratio'yu %45'ten %78'e çıkardı ve origin request'leri %60 azalttı.

Kullanım Senaryosu 2: Security Header'ları

Security header'ları eklemek için CloudFront Functions kullanmak Lambda@Edge'den daha maliyet-etkin.

javascript
// Security header'ları için CloudFront Function (viewer response)function handler(event) {    var response = event.response;    var headers = response.headers;
    // Strict-Transport-Security (HSTS)    headers['strict-transport-security'] = {        value: 'max-age=31536000; includeSubDomains; preload'    };
    // Content-Security-Policy (CSP)    headers['content-security-policy'] = {        value: "default-src 'self'; img-src 'self' https: data:; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';"    };
    // X-Content-Type-Options    headers['x-content-type-options'] = {        value: 'nosniff'    };
    // X-Frame-Options    headers['x-frame-options'] = {        value: 'DENY'    };
    // X-XSS-Protection    headers['x-xss-protection'] = {        value: '1; mode=block'    };
    // Referrer-Policy    headers['referrer-policy'] = {        value: 'strict-origin-when-cross-origin'    };
    // Permissions-Policy    headers['permissions-policy'] = {        value: 'geolocation=(), microphone=(), camera=()'    };
    return response;}

Aylık 5 milyar request için bu CloudFront Functions ile 500amalolurkenLambda@Edgeile500'a mal olurken Lambda@Edge ile 3,000+ tutabiliyor.

Kullanım Senaryosu 3: KeyValueStore ile A/B Testing

CloudFront Functions, yeniden deploy olmadan dinamik konfigürasyon için KeyValueStore'u destekliyor.

javascript
// A/B testing için KeyValueStore kullanan CloudFront Functionimport cf from 'cloudfront';
const kvsId = 'a1b2c3d4-5678-90ab-cdef-example12345';const kvsHandle = cf.kvs(kvsId);
async function handler(event) {    var request = event.request;    var uri = request.uri;
    // Kullanıcının zaten experiment ataması var mı kontrol et    var cookies = request.cookies;    var experimentCookie = cookies['experiment_variant'];
    var variant;    if (experimentCookie) {        variant = experimentCookie.value;    } else {        // Experiment konfigürasyonunu KeyValueStore'dan al        var experimentConfig = await kvsHandle.get('experiment_homepage');        var config = JSON.parse(experimentConfig);
        // Traffic split'e göre variant ata        var random = Math.random() * 100;        if (random < config.variantA_percentage) {            variant = 'A';        } else if (random < (config.variantA_percentage + config.variantB_percentage)) {            variant = 'B';        } else {            variant = 'C';        }
        // Gelecekteki request'ler için cookie set et        request.cookies['experiment_variant'] = { value: variant };    }
    // URL'i variant'a göre yeniden yaz    if (uri === '/') {        request.uri = `/variants/home-${variant.toLowerCase()}.html`;    }
    return request;}

Tip: KeyValueStore güncellemeleri birkaç dakika içinde yayılıyor. Development sırasında versioning kullan ve production değişiklikleri için gradual rollout uygula.

Lambda@Edge: Güç ve Esneklik

Lambda@Edge, network erişimi, harici API'ler veya karmaşık business logic gerektiren kompleks operasyonları ele alıyor. Trade-off olarak daha yüksek maliyet ve potansiyel cold start latency var.

Kullanım Senaryosu 1: Geo-Targeting ve Lokalizasyon

CloudFront, Lambda@Edge'in intelligent routing için kullanabileceği coğrafi header'lar sağlıyor.

javascript
// Geo-targeting için Lambda@Edge function (viewer request)'use strict';
exports.handler = (event, context, callback) => {    const request = event.Records[0].cf.request;    const headers = request.headers;
    // CloudFront geo header'ları sağlıyor    const country = headers['cloudfront-viewer-country']        ? headers['cloudfront-viewer-country'][0].value        : 'US';
    // Ülkeleri dil tercihlerine map et    const countryToLocale = {        'DE': '/de',        'AT': '/de',        'CH': '/de',        'TR': '/tr',        'FR': '/fr',        'ES': '/es',        'IT': '/it',        'US': '/en',        'GB': '/en',        'CA': '/en'    };
    // Sadece root path'i redirect et    if (request.uri === '/') {        const locale = countryToLocale[country] || '/en';
        // Kullanıcının locale tercihi cookie'si var mı kontrol et        const cookies = headers.cookie || [];        let localePreference = null;
        for (let cookie of cookies) {            const matches = cookie.value.match(/locale=([^;]+)/);            if (matches) {                localePreference = matches[1];                break;            }        }
        // Lokalize edilmiş path'e redirect et        const targetUri = localePreference || locale;
        const response = {            status: '302',            statusDescription: 'Found',            headers: {                'location': [{                    key: 'Location',                    value: targetUri                }],                'cache-control': [{                    key: 'Cache-Control',                    value: 'max-age=3600'                }]            }        };
        callback(null, response);    } else {        callback(null, request);    }};

Kullanım Senaryosu 2: JWT Authentication

JWT token'ları edge'de doğrulamak, unauthorized request'lerin origin'e ulaşmasını önlüyor.

javascript
// JWT validation için Lambda@Edge function (viewer request)'use strict';
const jwt = require('jsonwebtoken');
// Production'da AWS Secrets Manager'dan çekconst JWT_SECRET = process.env.JWT_SECRET;
exports.handler = async (event, context, callback) => {    const request = event.Records[0].cf.request;    const headers = request.headers;
    // Protected path'ler    const protectedPaths = ['/api/', '/dashboard/', '/admin/'];    const isProtected = protectedPaths.some(path => request.uri.startsWith(path));
    if (!isProtected) {        callback(null, request);        return;    }
    // Authorization header'ını çıkar    const authHeader = headers.authorization || headers.Authorization;
    if (!authHeader || authHeader.length === 0) {        callback(null, unauthorizedResponse('Missing authorization header'));        return;    }
    const token = authHeader[0].value.replace('Bearer ', '');
    try {        // JWT token'ı doğrula        const decoded = jwt.verify(token, JWT_SECRET, {            algorithms: ['HS256'],            maxAge: '24h'        });
        // Origin için custom header'lara kullanıcı bilgisi ekle        request.headers['x-user-id'] = [{            key: 'X-User-Id',            value: decoded.userId        }];        request.headers['x-user-email'] = [{            key: 'X-User-Email',            value: decoded.email        }];
        callback(null, request);    } catch (error) {        console.error('JWT validation failed:', error.message);        callback(null, unauthorizedResponse('Invalid or expired token'));    }};
function unauthorizedResponse(message) {    return {        status: '401',        statusDescription: 'Unauthorized',        headers: {            'www-authenticate': [{                key: 'WWW-Authenticate',                value: 'Bearer realm="Access to protected resources"'            }],            'content-type': [{                key: 'Content-Type',                value: 'application/json'            }]        },        body: JSON.stringify({            error: message        })    };}

Tip: Lambda@Edge function'larında asla secret'ları hardcode etme. API call'larını ve cold start etkisini minimize etmek için caching ile AWS Secrets Manager kullan.

Kullanım Senaryosu 3: Origin Selection ve Failover

Health check'lerle dinamik origin routing, dayanıklı mimariler sağlıyor.

javascript
// Origin selection için Lambda@Edge function (origin request)'use strict';
const https = require('https');
exports.handler = async (event, context, callback) => {    const request = event.Records[0].cf.request;
    // Primary ve secondary origin'ler    const origins = {        primary: {            domainName: 'api-primary.example.com',            port: 443,            protocol: 'https',            path: '/v1'        },        secondary: {            domainName: 'api-secondary.example.com',            port: 443,            protocol: 'https',            path: '/v1'        }    };
    let selectedOrigin = origins.primary;
    // Custom header'a göre route et    const routingHeader = request.headers['x-origin-override'];    if (routingHeader && routingHeader[0].value === 'secondary') {        selectedOrigin = origins.secondary;    }
    // Path'e göre route et    if (request.uri.startsWith('/legacy/')) {        selectedOrigin = origins.secondary;    }
    // Primary origin'i health check yap    try {        const isHealthy = await checkOriginHealth(selectedOrigin.domainName);        if (!isHealthy) {            console.log(`Primary origin ${selectedOrigin.domainName} unhealthy, failing over`);            selectedOrigin = origins.secondary;        }    } catch (error) {        console.error('Health check failed:', error);        selectedOrigin = origins.secondary;    }
    // Request'i seçilen origin ile güncelle    request.origin = {        custom: {            domainName: selectedOrigin.domainName,            port: selectedOrigin.port,            protocol: selectedOrigin.protocol,            path: selectedOrigin.path,            sslProtocols: ['TLSv1.2'],            readTimeout: 30,            keepaliveTimeout: 5,            customHeaders: {}        }    };
    callback(null, request);};
function checkOriginHealth(domainName) {    return new Promise((resolve) => {        const options = {            hostname: domainName,            port: 443,            path: '/health',            method: 'GET',            timeout: 2000        };
        const req = https.request(options, (res) => {            resolve(res.statusCode === 200);        });
        req.on('error', () => resolve(false));        req.on('timeout', () => {            req.destroy();            resolve(false);        });
        req.end();    });}

Performans Optimizasyonu

Lambda@Edge Cold Start'ları Azaltmak

Cold start'lar, function'lar viewer request fazında çalıştığında kullanıcı deneyimini doğrudan etkiliyor. İşe yarayan yöntemler:

1. Package Size'ı Minimize Et

javascript
// KÖTÜ: Handler içinde initialize etexports.handler = async (event) => {    const AWS = require('aws-sdk'); // Yavaş!    const dynamodb = new AWS.DynamoDB.DocumentClient();    // ...};
// İYİ: Handler dışında initialize etconst AWS = require('aws-sdk');const dynamodb = new AWS.DynamoDB.DocumentClient();
exports.handler = async (event) => {    // Warm invocation'larda initialization'ı yeniden kullanır};

2. Memory Allocation'ı Doğru Boyutlandır

Daha fazla memory, daha fazla CPU demek ve bu da cold start süresini azaltıyor. Test'ler orta düzeyde dependency'leri olan Lambda@Edge function'lar için 512 MB'nin genellikle ideal nokta olduğunu gösterdi.

3. External Dependency'leri Azalt

Ağır kütüphaneleri daha hafif alternatiflerle değiştir:

  • moment.jsdate-fns veya native Date
  • Tam AWS SDK → bireysel service client'ları
  • Büyük image processing kütüphaneleri → minimal implementasyon'lar

Production sistemlerden cold start metrikleri:

  • Boş function: 100-300ms
  • AWS SDK ile: 500-1000ms
  • Sharp ile (image processing): 1000-3000ms

CloudFront Functions Optimizasyonu

Kodu Minimal Tut: 10 KB limiti tüm kodu içeriyor. Hardcode değerler yerine konfigürasyon verisi için KeyValueStore kullan.

KeyValueStore'dan Yararlan: Function yeniden deploy'u önlemek için konfigürasyon verisini offload et. KeyValueStore sub-milisaniye okuma ile 5 MB storage sağlıyor.

Maliyet Analizi ve Optimizasyon

Maliyet yapısını anlamak bilinçli kararlar almaya yardımcı oluyor.

Detaylı Maliyet Hesaplama

Senaryo: Aylık 5 milyar request, 50ms ortalama süre, 128 MB memory

CloudFront Functions:

5,000M invocation × $0.10 = $500Toplam: $500/ay

Lambda@Edge:

Request charge'ları: 5,000M × $0.60 = $3,000Compute: 5,000M × 0.05s × 0.125GB × $0.00005001 = $1,563Toplam: $4,563/ay

Tasarruf: CloudFront Functions kullanarak $4,063/ay (%89 azalma)

Maliyet Optimizasyon Stratejileri

1. Mümkün Olduğunda CloudFront Functions Kullan: Header manipülasyonu ve cache key normalizasyonu gibi operasyonlar için CloudFront Functions 5-8x maliyet tasarrufu sağlıyor.

2. Lambda@Edge Memory'yi Optimize Et: CloudWatch metrikleri kullanarak memory allocation'ı doğru boyutlandır. Daha fazla memory, execution süresini azaltarak daha yüksek memory maliyetlerini dengeleyebilir.

3. Invocation Frekansını Azalt: Edge function invocation'larını minimize etmek için CloudFront cache policy'lerini etkili kullan. Her cache'lenen response bir function invocation'dan kaçınır.

4. Gerçek Kullanımı İzle: Maliyet threshold'ları için CloudWatch alarm'ları kur:

typescript
import * as cloudwatch from 'aws-cdk-lib/aws-cloudwatch';
const lambdaEdgeCostAlarm = new cloudwatch.Alarm(this, 'LambdaEdgeCostAlarm', {    metric: new cloudwatch.Metric({        namespace: 'AWS/Lambda',        metricName: 'Invocations',        dimensionsMap: {            FunctionName: edgeFunction.functionName,        },        statistic: 'Sum',        period: cdk.Duration.days(1),    }),    threshold: 1_000_000_000, // günde 1 milyar invocation    evaluationPeriods: 1,    alarmDescription: 'Lambda@Edge invocation budget threshold aşıldı',});

Debugging ve Logging Zorlukları

Lambda@Edge logları function'ın çalıştığı AWS bölgesinde oluşuyor, bu da debugging'i karmaşık hale getiriyor.

Bölgeler Arasında Log'ları Bulmak

CloudFront Response Header'larını Kontrol Et:

bash
curl -I https://your-distribution.cloudfront.net/path# Ara: x-amz-cf-pop: IAD89-P1# IAD = us-east-1 region

Havaalanı Kodu-Region Eşlemesi:

  • IAD (Dulles) → us-east-1
  • SFO (San Francisco) → us-west-1
  • DUB (Dublin) → eu-west-1
  • NRT (Tokyo) → ap-northeast-1
  • SYD (Sydney) → ap-southeast-2

Structured Logging Best Practice

javascript
// Structured logging ile Lambda@Edge function'use strict';
exports.handler = async (event, context) => {    const request = event.Records[0].cf.request;    const requestId = context.requestId;
    // Kolay parse için structured log    const logContext = {        requestId,        uri: request.uri,        method: request.method,        country: request.headers['cloudfront-viewer-country']?.[0]?.value,        timestamp: new Date().toISOString(),    };
    console.log('REQUEST_START', JSON.stringify(logContext));
    try {        // Logic'in burada        console.log('PROCESSING', JSON.stringify({ ...logContext, step: 'validation' }));
        return request;    } catch (error) {        console.error('ERROR', JSON.stringify({            ...logContext,            error: error.message,            stack: error.stack,        }));        throw error;    } finally {        console.log('REQUEST_END', JSON.stringify(logContext));    }};

Structured log'ları sorgulamak için CloudWatch Logs Insights kullan:

fields @timestamp, @message| filter @message like /ERROR/| sort @timestamp desc| limit 100

Yaygın Tuzaklar ve Çözümler

1. Lambda@Edge Response Size Aşıldı (502 Error)

Problem: Function >1 MB response dönüyor, CloudFront 502 veriyor.

Çözüm: Dönmeden önce response size'ını kontrol et:

javascript
const responseBody = JSON.stringify(data);const sizeInBytes = Buffer.byteLength(responseBody, 'utf8');
if (sizeInBytes > 1048576) { // 1 MB = 1048576 byte    console.error(`Response size ${sizeInBytes} 1MB limitini aşıyor`);    // Bunun yerine S3 object referansı dön    return {        status: '200',        body: JSON.stringify({            url: `https://s3.amazonaws.com/bucket/response-${requestId}.json`        })    };}

2. Viewer Request Timeout (5 Saniye)

Problem: Viewer request Lambda@Edge function timeout veriyor.

Çözüm: Timeout koruması için Promise.race kullan:

javascript
const timeoutPromise = new Promise((_, reject) =>    setTimeout(() => reject(new Error('Timeout')), 4000));
const result = await Promise.race([    fetchExternalData(),    timeoutPromise]);

3. Cache Key Verimsizliği Duplicate Object'ler Yaratıyor

Problem: Cache hit ratio düşük, yüksek origin request'leri.

Çözüm: Query parameter'ları normalize et:

javascript
function normalizeQueryString(querystring) {    // Tracking parameter'larını kaldır    const trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'fbclid', 'gclid'];    trackingParams.forEach(param => delete querystring[param]);
    // Kalan parameter'ları sırala    const sorted = {};    Object.keys(querystring).sort().forEach(key => {        sorted[key] = querystring[key];    });
    return sorted;}

AWS CDK Deployment Pattern

CloudFront'u edge function'larla deploy etmek için eksiksiz CDK stack:

typescript
// Edge function'larla CloudFront için AWS CDK stackimport * as cdk from 'aws-cdk-lib';import * as cloudfront from 'aws-cdk-lib/aws-cloudfront';import * as origins from 'aws-cdk-lib/aws-cloudfront-origins';import * as lambda from 'aws-cdk-lib/aws-lambda';import * as s3 from 'aws-cdk-lib/aws-s3';import { Construct } from 'constructs';import * as path from 'path';
export class EdgeComputingStack extends cdk.Stack {  constructor(scope: Construct, id: string, props?: cdk.StackProps) {    // ÖNEMLİ: Lambda@Edge us-east-1'de deploy edilmeli    super(scope, id, { ...props, env: { region: 'us-east-1' } });
    // Origin için S3 bucket    const bucket = new s3.Bucket(this, 'OriginBucket', {      blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,      encryption: s3.BucketEncryption.S3_MANAGED,    });
    // Cache key normalizasyonu için CloudFront Function    const cacheKeyFunction = new cloudfront.Function(this, 'CacheKeyNormalization', {      code: cloudfront.FunctionCode.fromFile({        filePath: path.join(__dirname, '../functions/cache-key-normalization.js'),      }),      runtime: cloudfront.FunctionRuntime.JS_2_0,      comment: 'Daha iyi hit ratio için cache key normalize et',    });
    // Security header'ları için CloudFront Function    const securityHeadersFunction = new cloudfront.Function(this, 'SecurityHeaders', {      code: cloudfront.FunctionCode.fromFile({        filePath: path.join(__dirname, '../functions/security-headers.js'),      }),      runtime: cloudfront.FunctionRuntime.JS_2_0,      comment: 'Tüm response'lara security header ekle',    });
    // JWT authentication için Lambda@Edge function    const jwtAuthFunction = new cloudfront.experimental.EdgeFunction(      this,      'JwtAuthFunction',      {        runtime: lambda.Runtime.NODEJS_20_X,        handler: 'index.handler',        code: lambda.Code.fromAsset(path.join(__dirname, '../lambda/jwt-auth')),        timeout: cdk.Duration.seconds(5),        memorySize: 128,      }    );
    // Optimize caching için cache policy    const cachePolicy = new cloudfront.CachePolicy(this, 'OptimizedCachePolicy', {      cachePolicyName: 'EdgeComputingOptimized',      comment: 'Normalize key'lerle optimize cache policy',      defaultTtl: cdk.Duration.hours(24),      maxTtl: cdk.Duration.days(365),      minTtl: cdk.Duration.seconds(1),      enableAcceptEncodingGzip: true,      enableAcceptEncodingBrotli: true,      headerBehavior: cloudfront.CacheHeaderBehavior.allowList(        'CloudFront-Viewer-Country',        'CloudFront-Viewer-Country-Region'      ),      queryStringBehavior: cloudfront.CacheQueryStringBehavior.allowList(        'w', 'h', 'q', 'format'      ),    });
    // CloudFront distribution    const distribution = new cloudfront.Distribution(this, 'Distribution', {      defaultBehavior: {        origin: new origins.S3Origin(bucket),        viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,        cachePolicy,        functionAssociations: [          {            function: cacheKeyFunction,            eventType: cloudfront.FunctionEventType.VIEWER_REQUEST,          },          {            function: securityHeadersFunction,            eventType: cloudfront.FunctionEventType.VIEWER_RESPONSE,          },        ],        edgeLambdas: [          {            functionVersion: jwtAuthFunction.currentVersion,            eventType: cloudfront.LambdaEdgeEventType.VIEWER_REQUEST,          },        ],      },      enableLogging: true,      logIncludesCookies: true,    });
    // Output'lar    new cdk.CfnOutput(this, 'DistributionDomainName', {      value: distribution.distributionDomainName,    });
    new cdk.CfnOutput(this, 'DistributionId', {      value: distribution.distributionId,    });  }}

Warning: Lambda@Edge function'ları CloudFront distribution'ınızın nerede deploy edildiğine bakılmaksızın her zaman us-east-1 bölgesinde oluşturulmalı.

Önemli Çıkarımlar

  1. İş için doğru servisi seç: CloudFront Functions kullanım senaryolarının %90'ı için (header'lar, cache key'ler, basit logic), Lambda@Edge karmaşık gereksinimler için (API'ler, authentication, image processing). Maliyet farkı 5-8x.

  2. Cold start'lar kullanıcı deneyimini etkiliyor: Lambda@Edge cold start'ları kullanıcıları doğrudan etkiliyor. Package size'ı minimize et, initialization'ı optimize et, latency-sensitive operasyonlar için CloudFront Functions kullan.

  3. 1 MB response limit kesin: Lambda@Edge >1 MB response dönemez. Mimariyi buna göre tasarla: büyük payload'ları S3 üzerinden stream et.

  4. Log'lar global olarak dağıtılmış: Lambda@Edge logları birden fazla AWS bölgesinde görünüyor. Correlation ID'lerle structured logging kullan, doğru bölgeyi bulmak için x-amz-cf-pop header'ını kontrol et.

  5. Cache optimizasyonu kritik: Cache hit ratio'yu iyileştirmek için CloudFront Functions ile cache key'leri normalize et. Kötü cache key tasarımı duplicate object'ler yaratır ve origin load'u artırır.

  6. CloudFront Functions ile security header'ları: HSTS, CSP, X-Frame-Options eklemek CloudFront Functions ile 1M request başına 0.10amalolurkenLambda@Edgeile0.10'a mal olurken Lambda@Edge ile 6+.

  7. KeyValueStore dinamik konfigürasyon sağlıyor: Function'ları yeniden deploy etmeden A/B test yüzdelerini, feature flag'leri ve routing kurallarını güncelle. 5 MB storage, sub-milisaniye okuma.

  8. Maliyetleri sürekli izle: Edge function'lar milyarlarca invocation'a scale olabiliyor. CloudWatch alarm'ları kur, aylık maliyetleri gözden geçir, agresif optimize et.

  9. Failover senaryolarını test et: Edge function'lar critical path'in parçası. Graceful error handling uygula, hata durumunda orijinal request'i dön, error rate'leri izle.

  10. Basit başla, progressif scale et: CloudFront managed policy'lerle başla, optimizasyon için CloudFront Functions ekle, Lambda@Edge'i sadece gerektiğinde devreye sok. Her adımda etkiyi ölç.

Edge computing ile çalışmak bana CloudFront Functions ve Lambda@Edge arasındaki doğru seçimin spesifik gereksinimlere bağlı olduğunu öğretti. Basit başlamak ve sadece gerektiğinde karmaşıklık eklemek, en maliyet-etkin ve sürdürülebilir çözümleri üretiyor.

İlgili Yazılar