# 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.ts5 process-payment/6 index.ts7 _shared/8 cors.ts9 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.ts2import { corsHeaders } from '../_shared/cors.ts'3 4Deno.serve(async (req: Request) => {5 // OPTIONS preflight için early return6 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.ts2export 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# Login2supabase login3 4# Local dev (fonksiyonu local'de test et)5supabase functions serve hello-world --env-file .env.local6 7# Production deploy8supabase functions deploy hello-world9 10# Tüm fonksiyonları deploy et11supabase functions deployLocal 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ın4const supabaseAdmin = createClient(5 Deno.env.get('SUPABASE_URL') ?? '',6 Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? '',7 {8 auth: {9 autoRefreshToken: false,10 persistSession: false11 }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 al10 const authHeader = req.headers.get('Authorization')!11 12 // User context ile client oluştur - RLS aktif kalır13 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: false23 }24 }25 )26 27 // Bu query çağıran user'ın RLS policy'lerine tabi28 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 filtreler38 const { data, error } = await supabaseClient39 .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örebilir2CREATE POLICY "Users can view own profile"3ON profiles4FOR SELECT5USING (auth.uid() = user_id);6 7-- Kullanıcılar sadece kendi verilerini güncelleyebilir8CREATE POLICY "Users can update own profile"9ON profiles10FOR UPDATE11USING (auth.uid() = user_id)12WITH CHECK (auth.uid() = user_id);13 14-- Admin rolü tüm verilere erişebilir15CREATE POLICY "Admins can do everything"16ON profiles17FOR ALL18USING (19 EXISTS (20 SELECT 1 FROM user_roles21 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ştur2CREATE OR REPLACE FUNCTION public.handle_new_user()3RETURNS trigger AS $$4BEGIN5 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 ekle17CREATE TRIGGER on_auth_user_created18 AFTER INSERT ON auth.users19 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.ts2Deno.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?.id11 const email = payload.user?.email12 13 // Custom claim ekle14 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ü çek37 const supabaseAdmin = createAdminClient()38 const { data } = await supabaseAdmin39 .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.ts2Deno.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.user10 11 // Paralel işlemler başlat12 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.ts2import { createClient } from 'npm:@supabase/supabase-js@2'3 4interface StorageWebhookPayload {5 type: 'INSERT' | 'UPDATE' | 'DELETE'6 table: string7 record: {8 bucket_id: string9 name: string10 owner: string11 created_at: string12 updated_at: string13 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şle22 if (23 payload.type === 'INSERT' &&24 payload.record.bucket_id === 'avatars'25 ) {26 const filePath = payload.record.name27 const userId = payload.record.owner28 29 try {30 // Görsel optimizasyonu31 await processImage(filePath, userId)32 33 // Metadata güncelle34 const supabaseAdmin = createAdminClient()35 await supabaseAdmin36 .from('profiles')37 .update({38 avatar_updated_at: new Date().toISOString(),39 avatar_processed: true40 })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ştur56 // Bu kısım use case'e göre değişir57 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 ekle2supabase secrets set STRIPE_SECRET_KEY=sk_live_xxx3supabase secrets set SENDGRID_API_KEY=SG.xxx4 5# Tüm secret'ları listele (değerler gizli)6supabase secrets list7 8# Edge Function içinde kullan9const 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ştir2CREATE EXTENSION IF NOT EXISTS vault;3 4-- Secret ekle5SELECT vault.create_secret('stripe_key', 'sk_live_xxx', 'Stripe production key');6 7-- Secret'ı oku8SELECT decrypted_secret9FROM vault.decrypted_secrets10WHERE name = 'stripe_key';typescript
1// Edge Function'dan Vault secret'ı oku2Deno.serve(async (req) => {3 const supabaseAdmin = createAdminClient()4 5 const { data: secretData } = await supabaseAdmin6 .rpc('get_secret', { secret_name: 'stripe_key' })7 8 const stripeKey = secretData?.decrypted_secret9 10 // Stripe işlemi yap11 // ...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.ts2Deno.serve(async (req) => {3 const { orderId } = await req.json()4 5 // Hemen yanıt dön - client beklemez6 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ışır12 EdgeRuntime.waitUntil(processOrderInBackground(orderId))13 14 return response15})16 17async function processOrderInBackground(orderId: string) {18 // Uzun süren işlemler burada19 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ştur2SELECT pgmq.create('order_processing');3 4-- Edge Function içinden message ekle5SELECT pgmq.send(6 'order_processing',7 '{"orderId": "123", "action": "process"}'::jsonb8);9 10-- Ayrı bir consumer Edge Function mesajları işler11SELECT * 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ği2Deno.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 ilet19 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ği14 socket.send(`Echo: ${event.data}`)15 })16 17 return response18})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çin2Deno.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.ts2// Geliştirme ve production için ayrı origin'ler3const 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 ? origin12 : 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 exchange15 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önlendir22 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: 256MB3Request: 6MB body size4Response: 6MB (streaming için sınırsız)5Timeout: 150 saniye6Cold Start: ~100msProduction Stratejisi:
- Cold start minimize etmek için fonksiyonları küçük tutun
- Database bağlantılarını fonksiyon top-level'da initialize etmeyin, request başına yapın
- Büyük npm paketleri yerine hafif alternatifler tercih edin
- Edge logs'u aktif olarak izleyin (Supabase Dashboard > Edge Functions > Logs)
- Error tracking için Sentry Edge SDK entegre edin
typescript
1// Performance-optimized Edge Function pattern2import { createClient, SupabaseClient } from 'npm:@supabase/supabase-js@2'3 4// Module-level cache - warm instance'larda yeniden kullanılır5let _adminClient: SupabaseClient | null = null6 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 _adminClient16}17 18Deno.serve(async (req: Request) => {19 // Preflight - erken dön20 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 validation30 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 check41 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 kullan50 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=brkEaster Egg
Gizli bir bilgi buldun!
Bu bölümde gizli bir bilgi var. Keşfetmek ister misin?
typescript
1// test/edge-function.test.ts2import { assertEquals } from 'jsr:@std/assert'3 4// Local dev server URL5const 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ır2deno 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:

