Tüm Yazılar
KategoriBackend
Okuma Süresi
14 dk okuma
Yayın Tarihi
...
Kelime Sayısı
3.009kelime

Kahveni hazırla - bu içerikli bir makale!

Supabase Edge Functions, Deno 2 runtime, Postgres RLS entegrasyonu, Auth/Storage webhooks, cold start optimizasyonu ve gerçek dünya deploy deneyimi.

Supabase Edge Functions: Deno Runtime ile Serverless Backend 2026

# Supabase Edge Functions: Deno Runtime ile Serverless Backend 2026

Serverless backend mimarisinde en kritik sorun her zaman aynı olmuştur: cold start süresi. AWS Lambda Node.js runtime için 400-800ms cold start süreleri üretim ortamlarında gerçek sorunlar yaratıyor. Supabase Edge Functions ise Deno 2 runtime üzerine inşa edilmiş mimarisiyle bu denklemi tamamen değiştiriyor. Gerçek dünya benchmark'larında ~100ms cold start ile Node.js tabanlı alternatiflerin dörtte biri süreye ulaşıyor.

Bu yazıda Supabase Edge Functions'ı production ortamında kullanan bir senior developer perspektifinden ele alacağız. Deno 2'nin getirdiği yenilikleri, Postgres RLS entegrasyonunu, Auth ve Storage webhook'larını, secret yönetimini ve gerçek deployment deneyimini derinlemesine inceleyeceğiz.

💡 Pro Tip: Supabase Edge Functions için en kritik performans kazanımı Deno.serve() ile başlayan fonksiyonlarda import chain'i minimize etmektir. Her dış import cold start'a 2-5ms ekler. Top-level await yerine lazy initialization pattern kullanın.

İçindekiler

  • Deno 2 Runtime: Node.js'ten Ne Fark Var?
  • Supabase Edge Functions Mimarisi
  • İlk Edge Function: Temel Yapı ve Deploy
  • supabase-js İçinden Auth Token Yönetimi
  • Postgres RLS Trigger Pattern
  • Auth Hooks: beforeUser ve afterUser
  • Storage Webhook'ları
  • Secret Yönetimi: Vault Entegrasyonu
  • Background Tasks ve Deno Queue
  • Streaming Response ve WebSocket
  • Cold Start Benchmark'ları
  • CORS Patterns ve PKCE Flow
  • Pricing, Limitler ve Production Stratejisi
  • Sonuç

Deno 2 Runtime: Node.js'ten Ne Fark Var?

Deno 2, 2024 sonunda stable olarak yayınlandı ve Supabase Edge Functions'ın teknik altyapısını oluşturuyor. Node.js ile karşılaştırdığımızda temel farklar şunlar:

Güvenlik Modeli: Deno varsayılan olarak dosya sistemi, ağ veya ortam değişkenlerine erişim vermez. --allow-net, --allow-read gibi explicit izinler gerekir. Edge Functions ortamında bu izinler platform tarafından kontrol edilir.

Native TypeScript: Babel veya tsc pipeline'ına gerek yok. Deno TypeScript'i doğrudan çalıştırır. Type stripping yapar ve runtime'da çalışır.

URL-based imports: Node.js node_modules yerine Deno URL import kullanır. jsr: (JavaScript Registry) ve npm: prefix'leri ile hem modern hem legacy paketlere erişilir.

Web Standards First: fetch, Request, Response, Headers gibi Web API'ler native olarak desteklenir. Node.js'te ek polyfill gereken şeyler burada built-in.

Startup Hızı: V8 snapshot optimizasyonu ve küçük binary boyutu sayesinde cold start ~100ms. Node.js Lambda'da bu 400-800ms arasında değişir.

Deno 2 ile gelen en kritik yenilik ise Node.js compatibility layer'ının olgunlaşması. npm: prefix'i ile artık express, pg, stripe gibi Node.js paketlerini Deno'da doğrudan kullanabiliyorsunuz. Bu Supabase Edge Functions için devrim niteliğinde çünkü ekosistem kısıtlaması büyük ölçüde ortadan kalktı.


Supabase Edge Functions Mimarisi

Supabase Edge Functions, Deno Deploy üzerine inşa edilmiş özel bir runtime'da çalışır. Mimari şöyle işler:

Bir istek geldiğinde Supabase'in CDN katmanı isteği en yakın edge node'a yönlendirir. Edge node'da Deno runtime, fonksiyon kodunu V8 isolate içinde çalıştırır. Bu isolate Postgres bağlantısı için Supabase'in connection pooler'ına (PgBouncer) erişir.

Kritik bir nokta: Her Edge Function invocation kendi izole V8 context'inde çalışır. Global state paylaşımı yoktur. Bu hem güvenlik açısından avantajlı hem de stateful pattern'lar için constraint oluşturur.

Fonksiyonlar supabase/functions/ dizininde yaşar. Her fonksiyon kendi alt dizininde index.ts dosyasına sahiptir:

swift
1supabase/
2 functions/
3 hello-world/
4 index.ts
5 process-payment/
6 index.ts
7 _shared/
8 cors.ts
9 supabase-client.ts

_shared/ dizini fonksiyonlar arası paylaşılan yardımcı kodlar için kullanılır ve deploy'a dahil edilmez, sadece import edilebilir.


İlk Edge Function: Temel Yapı ve Deploy

Minimal bir Edge Function şöyle görünür:

typescript
1// supabase/functions/hello-world/index.ts
2import { corsHeaders } from '../_shared/cors.ts'
3 
4Deno.serve(async (req: Request) => {
5 // OPTIONS preflight için early return
6 if (req.method === 'OPTIONS') {
7 return new Response('ok', { headers: corsHeaders })
8 }
9 
10 try {
11 const { name } = await req.json()
12 const data = {
13 message: `Merhaba ${name}!`,
14 timestamp: new Date().toISOString(),
15 }
16 return new Response(JSON.stringify(data), {
17 headers: { ...corsHeaders, 'Content-Type': 'application/json' },
18 status: 200,
19 })
20 } catch (error) {
21 return new Response(JSON.stringify({ error: error.message }), {
22 headers: { ...corsHeaders, 'Content-Type': 'application/json' },
23 status: 400,
24 })
25 }
26})
typescript
1// supabase/functions/_shared/cors.ts
2export const corsHeaders = {
3 'Access-Control-Allow-Origin': '*',
4 'Access-Control-Allow-Headers':
5 'authorization, x-client-info, apikey, content-type',
6 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS, PUT, DELETE',
7}

Deploy için Supabase CLI kullanılır:

bash
1# Login
2supabase login
3 
4# Local dev (fonksiyonu local'de test et)
5supabase functions serve hello-world --env-file .env.local
6 
7# Production deploy
8supabase functions deploy hello-world
9 
10# Tüm fonksiyonları deploy et
11supabase functions deploy

Local geliştirmede supabase functions serve komutu Docker üzerinde çalışır ve hot reload destekler. Environment variable'lar için --env-file flag'i kullanılır.


supabase-js İçinden Auth Token Yönetimi

Edge Function'lardan Supabase'e erişirken iki farklı client pattern kullanılır. Hangi client kullanacağınız use case'e göre değişir:

1. Service Role Client (Admin işlemler için):

typescript
1import { createClient } from 'npm:@supabase/supabase-js@2'
2 
3// Bu client RLS bypass eder - dikkatli kullanın
4const supabaseAdmin = createClient(
5 Deno.env.get('SUPABASE_URL') ?? '',
6 Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? '',
7 {
8 auth: {
9 autoRefreshToken: false,
10 persistSession: false
11 }
12 }
13)

2. User Context Client (RLS aktif, güvenli):

typescript
1import { createClient } from 'npm:@supabase/supabase-js@2'
2import { corsHeaders } from '../_shared/cors.ts'
3 
4Deno.serve(async (req: Request) => {
5 if (req.method === 'OPTIONS') {
6 return new Response('ok', { headers: corsHeaders })
7 }
8 
9 // Authorization header'dan JWT token al
10 const authHeader = req.headers.get('Authorization')!
11 
12 // User context ile client oluştur - RLS aktif kalır
13 const supabaseClient = createClient(
14 Deno.env.get('SUPABASE_URL') ?? '',
15 Deno.env.get('SUPABASE_ANON_KEY') ?? '',
16 {
17 global: {
18 headers: { Authorization: authHeader },
19 },
20 auth: {
21 autoRefreshToken: false,
22 persistSession: false
23 }
24 }
25 )
26 
27 // Bu query çağıran user'ın RLS policy'lerine tabi
28 const { data: userData, error: userError } = await supabaseClient.auth.getUser()
29 
30 if (userError || !userData.user) {
31 return new Response(
32 JSON.stringify({ error: 'Unauthorized' }),
33 { headers: { ...corsHeaders, 'Content-Type': 'application/json' }, status: 401 }
34 )
35 }
36 
37 // Kullanıcıya ait verileri çek - RLS otomatik filtreler
38 const { data, error } = await supabaseClient
39 .from('user_documents')
40 .select('*')
41 
42 if (error) {
43 return new Response(
44 JSON.stringify({ error: error.message }),
45 { headers: { ...corsHeaders, 'Content-Type': 'application/json' }, status: 400 }
46 )
47 }
48 
49 return new Response(
50 JSON.stringify({ data }),
51 { headers: { ...corsHeaders, 'Content-Type': 'application/json' }, status: 200 }
52 )
53})

Bu pattern'ın kritik avantajı: Edge Function içinde bile RLS politikaları çalışır. Kullanıcı sadece kendi verilerine erişebilir, ekstra authorization kodu yazmak zorunda kalmazsınız.


Postgres RLS Trigger Pattern

Supabase'in en güçlü özelliklerinden biri Row Level Security. Ama Edge Functions ile entegre ederken bazı pattern'lar diğerlerinden çok daha etkili:

RLS Policy Örneği:

sql
1-- Kullanıcılar sadece kendi profil verilerini görebilir
2CREATE POLICY "Users can view own profile"
3ON profiles
4FOR SELECT
5USING (auth.uid() = user_id);
6 
7-- Kullanıcılar sadece kendi verilerini güncelleyebilir
8CREATE POLICY "Users can update own profile"
9ON profiles
10FOR UPDATE
11USING (auth.uid() = user_id)
12WITH CHECK (auth.uid() = user_id);
13 
14-- Admin rolü tüm verilere erişebilir
15CREATE POLICY "Admins can do everything"
16ON profiles
17FOR ALL
18USING (
19 EXISTS (
20 SELECT 1 FROM user_roles
21 WHERE user_id = auth.uid()
22 AND role = 'admin'
23 )
24);

Edge Function ile RLS Trigger Pattern:

Bazen bir Edge Function tetiklendiğinde Postgres'te otomatik işlem yapmanız gerekir. Bunun için Postgres trigger + Edge Function kombinasyonu kullanılır:

sql
1-- Yeni kullanıcı kaydında otomatik profil oluştur
2CREATE OR REPLACE FUNCTION public.handle_new_user()
3RETURNS trigger AS $$
4BEGIN
5 INSERT INTO public.profiles (id, email, full_name, created_at)
6 VALUES (
7 new.id,
8 new.email,
9 new.raw_user_meta_data ->> 'full_name',
10 now()
11 );
12 RETURN new;
13END;
14$$ LANGUAGE plpgsql SECURITY DEFINER;
15 
16-- Auth schema'daki users tablosuna trigger ekle
17CREATE TRIGGER on_auth_user_created
18 AFTER INSERT ON auth.users
19 FOR EACH ROW EXECUTE PROCEDURE public.handle_new_user();

Bu pattern Edge Function olmadan Postgres seviyesinde çalışır ve çok daha hızlıdır. Edge Function'ları bu tür basit durumlar için kullanmak yerine complex business logic için saklayın.


Auth Hooks: beforeUser ve afterUser

Supabase Auth Hooks, authentication lifecycle'ına müdahale etmenizi sağlar. Bu özellik custom business logic entegrasyonu için kritik:

beforeUser Hook (Custom Access Token):

typescript
1// supabase/functions/custom-access-token/index.ts
2Deno.serve(async (req) => {
3 const payload = await req.json()
4 
5 // Hook type kontrolü
6 if (payload.type !== 'before.user.create') {
7 return new Response(JSON.stringify({}), { status: 200 })
8 }
9 
10 const userId = payload.user?.id
11 const email = payload.user?.email
12 
13 // Custom claim ekle
14 const customClaims = {
15 user_role: await getUserRole(userId),
16 subscription_tier: await getSubscriptionTier(email),
17 feature_flags: await getFeatureFlags(userId),
18 }
19 
20 return new Response(
21 JSON.stringify({
22 decision: 'continue',
23 user: {
24 ...payload.user,
25 app_metadata: {
26 ...payload.user.app_metadata,
27 ...customClaims,
28 },
29 },
30 }),
31 { headers: { 'Content-Type': 'application/json' }, status: 200 }
32 )
33})
34 
35async function getUserRole(userId: string): Promise {
36 // DB'den kullanıcı rolünü çek
37 const supabaseAdmin = createAdminClient()
38 const { data } = await supabaseAdmin
39 .from('user_roles')
40 .select('role')
41 .eq('user_id', userId)
42 .single()
43 return data?.role ?? 'user'
44}

afterUser Hook (Post-signup İşlemler):

afterUser hook'u kullanıcı kaydından sonra çalışır. Email doğrulama, CRM sync, onboarding tetiklemek için idealdir:

typescript
1// supabase/functions/post-signup/index.ts
2Deno.serve(async (req) => {
3 const payload = await req.json()
4 
5 if (payload.type !== 'after.user.create') {
6 return new Response(JSON.stringify({}), { status: 200 })
7 }
8 
9 const user = payload.user
10 
11 // Paralel işlemler başlat
12 await Promise.all([
13 sendWelcomeEmail(user.email),
14 createUserInCRM(user),
15 initializeUserSettings(user.id),
16 ])
17 
18 return new Response(JSON.stringify({ success: true }), { status: 200 })
19})

Auth Hook'larını Supabase Dashboard'dan veya CLI ile kaydetmek gerekir. Dashboard'da Authentication > Hooks bölümünden fonksiyon URL'ini belirtirsiniz.


Storage Webhook'ları

Supabase Storage'a dosya yüklendiğinde veya silindiğinde Edge Function'ları tetikleyebilirsiniz. Bu özellik thumbnail oluşturma, virus scanning, metadata extraction için çok kullanışlı:

typescript
1// supabase/functions/storage-webhook/index.ts
2import { createClient } from 'npm:@supabase/supabase-js@2'
3 
4interface StorageWebhookPayload {
5 type: 'INSERT' | 'UPDATE' | 'DELETE'
6 table: string
7 record: {
8 bucket_id: string
9 name: string
10 owner: string
11 created_at: string
12 updated_at: string
13 metadata: Record
14 }
15 old_record: null | Record
16}
17 
18Deno.serve(async (req) => {
19 const payload: StorageWebhookPayload = await req.json()
20 
21 // Sadece image upload'larını işle
22 if (
23 payload.type === 'INSERT' &&
24 payload.record.bucket_id === 'avatars'
25 ) {
26 const filePath = payload.record.name
27 const userId = payload.record.owner
28 
29 try {
30 // Görsel optimizasyonu
31 await processImage(filePath, userId)
32 
33 // Metadata güncelle
34 const supabaseAdmin = createAdminClient()
35 await supabaseAdmin
36 .from('profiles')
37 .update({
38 avatar_updated_at: new Date().toISOString(),
39 avatar_processed: true
40 })
41 .eq('id', userId)
42 
43 } catch (error) {
44 console.error('Image processing failed:', error)
45 }
46 }
47 
48 return new Response(JSON.stringify({ processed: true }), {
49 headers: { 'Content-Type': 'application/json' },
50 status: 200,
51 })
52})
53 
54async function processImage(filePath: string, userId: string) {
55 // Sharp veya Cloudflare Images API ile thumbnail oluştur
56 // Bu kısım use case'e göre değişir
57 console.log(`Processing image for user ${userId}: ${filePath}`)
58}

Webhook'u kaydetmek için Supabase Dashboard'dan Database > Webhooks bölümüne gidin ve yeni webhook oluşturun. Storage schema'daki objects tablosuna INSERT event'i için fonksiyon URL'inizi belirtin.


Secret Yönetimi: Vault Entegrasyonu

Production'da API key'leri, webhook secret'larını ve diğer hassas değerleri yönetmek için Supabase iki yöntem sunar:

1. Environment Variables (Basit Kullanım):

bash
1# Secret ekle
2supabase secrets set STRIPE_SECRET_KEY=sk_live_xxx
3supabase secrets set SENDGRID_API_KEY=SG.xxx
4 
5# Tüm secret'ları listele (değerler gizli)
6supabase secrets list
7 
8# Edge Function içinde kullan
9const stripeKey = Deno.env.get('STRIPE_SECRET_KEY')

2. Vault (Şifreli, Rotatable):

Supabase Vault, secret'ları şifrelenmiş olarak Postgres'te saklar ve rotation desteği sunar:

sql
1-- Vault extension'ı aktifleştir
2CREATE EXTENSION IF NOT EXISTS vault;
3 
4-- Secret ekle
5SELECT vault.create_secret('stripe_key', 'sk_live_xxx', 'Stripe production key');
6 
7-- Secret'ı oku
8SELECT decrypted_secret
9FROM vault.decrypted_secrets
10WHERE name = 'stripe_key';
typescript
1// Edge Function'dan Vault secret'ı oku
2Deno.serve(async (req) => {
3 const supabaseAdmin = createAdminClient()
4 
5 const { data: secretData } = await supabaseAdmin
6 .rpc('get_secret', { secret_name: 'stripe_key' })
7 
8 const stripeKey = secretData?.decrypted_secret
9 
10 // Stripe işlemi yap
11 // ...
12})

Production'da kritik secret'lar için Vault tercih edin. Rotation gerektiğinde Edge Function'ı redeploy etmeden secret'ı güncelleyebilirsiniz.


Background Tasks ve Deno Queue

Edge Functions, HTTP response döndükten sonra da çalışmaya devam edebilir. Bu background tasks için kullanılır:

typescript
1// supabase/functions/process-order/index.ts
2Deno.serve(async (req) => {
3 const { orderId } = await req.json()
4 
5 // Hemen yanıt dön - client beklemez
6 const response = new Response(
7 JSON.stringify({ message: 'Sipariş işleme alındı', orderId }),
8 { headers: { 'Content-Type': 'application/json' }, status: 202 }
9 )
10 
11 // Background task başlat - response'tan sonra çalışır
12 EdgeRuntime.waitUntil(processOrderInBackground(orderId))
13 
14 return response
15})
16 
17async function processOrderInBackground(orderId: string) {
18 // Uzun süren işlemler burada
19 await sendOrderConfirmationEmail(orderId)
20 await updateInventory(orderId)
21 await notifyWarehouse(orderId)
22 await generateInvoice(orderId)
23}

EdgeRuntime.waitUntil() Cloudflare Workers'dan tanıdık bir API. Response döndükten sonra promise çözülene kadar process ayakta kalır. CPU time limiti (50ms default, max 2s) hala geçerlidir.

Daha uzun işlemler için Supabase Queues (pgmq tabanlı) kullanın:

sql
1-- Queue oluştur
2SELECT pgmq.create('order_processing');
3 
4-- Edge Function içinden message ekle
5SELECT pgmq.send(
6 'order_processing',
7 '{"orderId": "123", "action": "process"}'::jsonb
8);
9 
10-- Ayrı bir consumer Edge Function mesajları işler
11SELECT * FROM pgmq.read('order_processing', 30, 10);

Streaming Response ve WebSocket

Edge Functions, streaming response ve WebSocket desteği sunar:

typescript
1// Streaming AI response örneği
2Deno.serve(async (req) => {
3 const { prompt } = await req.json()
4 
5 const openAIResponse = await fetch('https://api.openai.com/v1/chat/completions', {
6 method: 'POST',
7 headers: {
8 'Authorization': `Bearer ${Deno.env.get('OPENAI_API_KEY')}`,
9 'Content-Type': 'application/json',
10 },
11 body: JSON.stringify({
12 model: 'gpt-4o',
13 messages: [{ role: 'user', content: prompt }],
14 stream: true,
15 }),
16 })
17 
18 // OpenAI stream'ini doğrudan client'a ilet
19 return new Response(openAIResponse.body, {
20 headers: {
21 'Content-Type': 'text/event-stream',
22 'Cache-Control': 'no-cache',
23 'Connection': 'keep-alive',
24 ...corsHeaders,
25 },
26 })
27})

WebSocket için Deno.upgradeWebSocket() kullanılır:

typescript
1Deno.serve((req) => {
2 if (req.headers.get('upgrade') !== 'websocket') {
3 return new Response(null, { status: 501 })
4 }
5 
6 const { socket, response } = Deno.upgradeWebSocket(req)
7 
8 socket.addEventListener('open', () => {
9 console.log('WebSocket bağlantısı açıldı')
10 })
11 
12 socket.addEventListener('message', (event) => {
13 // Echo server örneği
14 socket.send(`Echo: ${event.data}`)
15 })
16 
17 return response
18})

Cold Start Benchmark'ları

Gerçek dünya benchmark'larında Supabase Edge Functions rakiplerine göre belirgin şekilde daha hızlı:

Platform
Runtime
Ortalama Cold Start
Supabase Edge Functions
Deno 2
~100ms
Vercel Edge Functions
V8 Edge
~150ms
Cloudflare Workers
V8 Isolate
~50ms
AWS Lambda
Node.js 20
~400ms
AWS Lambda
Python 3.12
~600ms

Bu fark Deno'nun küçük binary boyutu ve V8 snapshot optimizasyonundan kaynaklanıyor. Deno runtime ~35MB, Node.js runtime ~80MB.

Production'da "always warm" stratejisi için fonksiyonları belirli aralıklarla ping eden bir cron job ekleyebilirsiniz:

typescript
1// supabase/functions/health-ping/index.ts - warmup için
2Deno.serve(() => {
3 return new Response(JSON.stringify({ status: 'warm', ts: Date.now() }), {
4 headers: { 'Content-Type': 'application/json' },
5 })
6})

CORS Patterns ve PKCE Flow

Browser'dan Edge Function çağrısı için CORS doğru kurulmak zorunda:

typescript
1// supabase/functions/_shared/cors.ts
2// Geliştirme ve production için ayrı origin'ler
3const allowedOrigins = [
4 'http://localhost:3000',
5 'https://myapp.com',
6 'https://staging.myapp.com',
7]
8 
9export function getCorsHeaders(origin: string | null) {
10 const allowedOrigin = origin && allowedOrigins.includes(origin)
11 ? origin
12 : allowedOrigins[0]
13 
14 return {
15 'Access-Control-Allow-Origin': allowedOrigin,
16 'Access-Control-Allow-Headers':
17 'authorization, x-client-info, apikey, content-type',
18 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS, PUT, DELETE',
19 'Access-Control-Max-Age': '86400',
20 }
21}

PKCE (Proof Key for Code Exchange) flow ile OAuth login için:

typescript
1Deno.serve(async (req) => {
2 const url = new URL(req.url)
3 const code = url.searchParams.get('code')
4 
5 if (!code) {
6 return new Response('Missing code', { status: 400 })
7 }
8 
9 const supabaseClient = createClient(
10 Deno.env.get('SUPABASE_URL') ?? '',
11 Deno.env.get('SUPABASE_ANON_KEY') ?? ''
12 )
13 
14 // PKCE code exchange
15 const { data, error } = await supabaseClient.auth.exchangeCodeForSession(code)
16 
17 if (error) {
18 return Response.redirect(`${Deno.env.get('SITE_URL')}/auth/error`)
19 }
20 
21 // Session cookie set et ve yönlendir
22 return Response.redirect(`${Deno.env.get('SITE_URL')}/dashboard`)
23})

Pricing, Limitler ve Production Stratejisi

Pricing:

  • Free tier: 500K invocation/ay
  • Pro: $2/1M invocation (ilk 2M dahil)
  • CPU time: 50ms default, 150ms ile artırılabilir
  • Memory: 256MB hard limit
  • Execution time: 150 saniye max

Kritik Limitler:

swift
1CPU Time: 50ms (default), 150ms (max)
2Memory: 256MB
3Request: 6MB body size
4Response: 6MB (streaming için sınırsız)
5Timeout: 150 saniye
6Cold Start: ~100ms

Production Stratejisi:

  1. Cold start minimize etmek için fonksiyonları küçük tutun
  2. Database bağlantılarını fonksiyon top-level'da initialize etmeyin, request başına yapın
  3. Büyük npm paketleri yerine hafif alternatifler tercih edin
  4. Edge logs'u aktif olarak izleyin (Supabase Dashboard > Edge Functions > Logs)
  5. Error tracking için Sentry Edge SDK entegre edin

typescript
1// Performance-optimized Edge Function pattern
2import { createClient, SupabaseClient } from 'npm:@supabase/supabase-js@2'
3 
4// Module-level cache - warm instance'larda yeniden kullanılır
5let _adminClient: SupabaseClient | null = null
6 
7function getAdminClient(): SupabaseClient {
8 if (!_adminClient) {
9 _adminClient = createClient(
10 Deno.env.get('SUPABASE_URL')!,
11 Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!,
12 { auth: { autoRefreshToken: false, persistSession: false } }
13 )
14 }
15 return _adminClient
16}
17 
18Deno.serve(async (req: Request) => {
19 // Preflight - erken dön
20 if (req.method === 'OPTIONS') {
21 return new Response(null, {
22 headers: {
23 'Access-Control-Allow-Origin': '*',
24 'Access-Control-Allow-Headers': 'authorization, content-type, apikey',
25 },
26 })
27 }
28 
29 // Request parse ve validation
30 let body: { action: string; data: unknown }
31 try {
32 body = await req.json()
33 } catch {
34 return new Response(JSON.stringify({ error: 'Invalid JSON' }), {
35 status: 400,
36 headers: { 'Content-Type': 'application/json' },
37 })
38 }
39 
40 // Auth check
41 const jwt = req.headers.get('Authorization')?.replace('Bearer ', '')
42 if (!jwt) {
43 return new Response(JSON.stringify({ error: 'Unauthorized' }), {
44 status: 401,
45 headers: { 'Content-Type': 'application/json' },
46 })
47 }
48 
49 // Cached admin client kullan
50 const admin = getAdminClient()
51 const { data: { user }, error: authError } = await admin.auth.getUser(jwt)
52 
53 if (authError || !user) {
54 return new Response(JSON.stringify({ error: 'Invalid token' }), {
55 status: 401,
56 headers: { 'Content-Type': 'application/json' },
57 })
58 }
59 
60 // Business logic...
61 return new Response(JSON.stringify({ success: true }), {
62 headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' },
63 })
64})

ALTIN İPUCU

Bu yazının en değerli bilgisi

Bu ipucu, yazının en önemli çıkarımını içeriyor.

bash
1supabase functions serve my-function --inspect-mode=brk

Easter Egg

Gizli bir bilgi buldun!

Bu bölümde gizli bir bilgi var. Keşfetmek ister misin?

typescript
1// test/edge-function.test.ts
2import { assertEquals } from 'jsr:@std/assert'
3 
4// Local dev server URL
5const BASE_URL = 'http://localhost:54321/functions/v1'
6 
7Deno.test('hello-world fonksiyonu çalışıyor', async () => {
8 const response = await fetch(`${BASE_URL}/hello-world`, {
9 method: 'POST',
10 headers: {
11 'Content-Type': 'application/json',
12 'Authorization': `Bearer ${Deno.env.get('SUPABASE_ANON_KEY')}`,
13 },
14 body: JSON.stringify({ name: 'Dünya' }),
15 })
16 
17 assertEquals(response.status, 200)
18 const data = await response.json()
19 assertEquals(data.message, 'Merhaba Dünya!')
20})
bash
1# Test çalıştır
2deno test --allow-net --allow-env test/

Okuyucu Ödülü

Sonuç

Supabase Edge Functions, Deno 2 runtime ile serverless backend geliştirmede önemli bir yere sahip. ~100ms cold start, native TypeScript desteği, Web Standards API'leri ve Postgres RLS entegrasyonu birlikte güçlü bir platform sunuyor.

En kritik noktalar:

  • User context client kullanarak RLS otomatik devreye girer, ekstra auth kodu yazmazsınız
  • Auth Hooks ile authentication lifecycle'ı tam kontrol altına alabilirsiniz
  • Storage Webhook'ları file processing pipeline'ı oluşturmanın en temiz yolu
  • Background tasks için EdgeRuntime.waitUntil() veya pgmq kullanın
  • CPU time ve memory limitleri göz önünde bulundurarak fonksiyonları küçük ve odaklı tutun

İlgili Kaynaklar:

Site İçi İlgili Yazılar:

Etiketler

#Supabase#Edge Functions#Deno#Serverless#Postgres#Backend#2026
Muhittin Çamdalı

Muhittin Çamdalı

Senior iOS Developer

12+ yıllık deneyime sahip iOS Developer. Swift, SwiftUI ve modern iOS mimarileri konusunda uzman. Apple platformlarında performanslı ve kullanıcı dostu uygulamalar geliştiriyorum.

iOS Geliştirme Haberleri

Haftalık Swift tips, SwiftUI tricks ve iOS best practices. Spam yok, sadece değerli içerik.

Gizliliğinize saygı duyuyoruz. İstediğiniz zaman abonelikten çıkabilirsiniz.

Paylaş

Bunu da begenebilirsiniz