Web razvoj
Next.jsSupabaseEdge FunctionsSaaSArhitekturaVercelCloudflareServer Actions

Next.js + Supabase Edge Functions: Praktična arhitektura za moderni SaaS (vodič za 2026.)

AO
Adrijan Omićević
·15 min čitanja

# Što ćeš izgraditi#

Ovaj vodič ti daje praktičnu, namjerno “opinionated” Next.js + Supabase Edge Functions arhitekturu za moderni SaaS: gdje živi koji kod, kako teku podaci i kako deployati bez spoticanja o runtime limite.

Naučit ćeš kada koristiti Supabase Edge Functions u odnosu na Next.js API rute i Server Actions, uz konkretne primjere za auth hookove, webhookove i background zadatke. Ako još odlučuješ koji auth pattern koristiti, kreni s našim vodičem Next.js authentication guide pa se vrati ovdje za arhitekturu i blueprint za deployment.

# Zašto ova arhitektura radi za SaaS#

SaaS aplikacije tipično imaju tri klase prometa:

  1. 1
    Promet aplikacije od ulogiranih korisnika, često zahtijeva sesije, upite zaštićene RLS-om i UI-driven workflowe.
  2. 2
    Promet providera od trećih strana poput Stripea, Postmarka, Sentryja, GitHuba ili custom enterprise sustava putem webhookova.
  3. 3
    Automatizacijski promet iz zakazanih zadataka, retrya i back-office workflowa.

Čista podjela smanjuje kompleksnost i incidente u produkciji. U praksi:

  • Next.js briljira u UI-ju, Server Actions i zahtjevima svjesnima sesije.
  • Supabase briljira u Postgresu, RLS-u, realtimeu, storageu i globalno dostupnim Edge Functions.
  • Supabase Edge Functions su odlične za endpointove prema van koji ne smiju ovisiti o deployu tvoje Next.js aplikacije, i za tokove koji profitiraju od blizine bazi.

🎯 Ključna poruka: Logiku vezanu uz UI stavi u Next.js, endpointove prema providerima u Supabase Edge Functions, a pristup podacima provodi kroz Postgres RLS kao zadanu zaštitnu ogradu.

# Okvir odluke: Edge Functions vs API rute vs Server Actions#

Najbrži način da srušiš ovu arhitekturu je tretirati sav server kod kao međusobno zamjenjiv. Nije zamjenjiv, pogotovo kad ubaciš runtime ograničenja, modele sesija i topologiju deploymenta.

Brza usporedna tablica#

Use caseNajbolji defaultZaštoKonkretan primjer
UI forma koja upisuje u DBServer ActionsUz UI, jednostavna validacija, koristi korisničku sesijuKreiranje projekta, poziv člana
UI treba custom JSON endpointAPI route ili Route HandlerRadi s fetchom, cachingom, middlewareom, može streamatiSearch endpoint, file proxy
Webhookovi trećih stranaSupabase Edge FunctionStabilan URL, deploy ne ovisi o Next.js, service role se može sigurno koristitiStripe invoice.paid webhook
Hookovi auth provideraSupabase Edge FunctionRadi blizu Supabase autha, minimalna latencija i couplingProvisioning nakon signupa
Lagani javni API blizu korisnikaSupabase Edge FunctionGlobalna distribucija, Deno runtime, mali overheadJavni status endpoint
Dugotrajni background joboviDedicated worker ili automation alatTimeouti i retry zahtijevaju queue semantikuUsklađivanje naplate
Zakazano održavanjeEdge Function sa schedulerom ili automationJednostavni cron-like okidačiDnevni usage rollup

Za runtime trade-offove i kad je Edge stvarno koristan, pročitaj naš deep dive: Next.js Edge runtime vs Node.js runtime on Vercel and Cloudflare.

Koristi Supabase Edge Functions kada#

  1. 1

    Pozivatelj nije tvoj Next.js frontend
    Webhookovi i callbackovi providera ne bi smjeli ovisiti o životnom ciklusu Next.js deploymenta.

  2. 2

    Trebaš Supabase service role key
    Edge Functions su sigurno mjesto za service role operacije poput privilegiranih upisa, cross-tenant administrativnih zadataka i po potrebi zaobilaženja RLS-a.

  3. 3

    Želiš stabilan, globalno dohvatljiv endpoint
    Mnogi SaaS timovi deployaju Next.js na Vercel, a svejedno trebaju provider endpointove neovisne o Vercel build rolloutima.

Preferiraj Next.js Server Actions kada#

  1. 1
    Zahtjev dolazi iz UI-ja i prirodno pripada route treeju.
  2. 2
    Trebaš čvrstu povezanost s React component stateom i server-side validacijom.
  3. 3
    RLS je dovoljan i ne trebaš service role privilegije.

Preferiraj Next.js API Routes ili Route Handlers kada#

  1. 1
    Trebaš klasičan endpoint koji konzumira više klijenata, uključujući mobilne aplikacije.
  2. 2
    Treba ti streaming, file proxying ili posebni headeri.
  3. 3
    Integriraš Node-only biblioteke koje su nespretne u Edge runtimeovima.

⚠️ Upozorenje: Nemoj graditi cijeli backend iza Supabase Edge Functions samo zato što postoje. Ako je zahtjev UI-driven i zaštićen RLS-om, Next.js Server Actions su jednostavnije, jeftinije za održavanje i lakše za end-to-end testiranje.

# Pregled referentne arhitekture#

Na visokoj razini, tvoj SaaS bi trebao izgledati ovako:

  • Next.js aplikacija rješava renderiranje, akcije svjesne sesije i UI workflowe.
  • Supabase Postgres je source of truth s RLS policyjima koji provode granice tenant-a.
  • Supabase Edge Functions implementiraju:
    • Webhookove od providera
    • Hookove životnog ciklusa autentikacije
    • Zakazane rollupove i cleanup jobove
  • Opcionalno: n8n automatizacije za orkestraciju workflowa, retrye, notifikacije i “integration glue”.

Ako želiš širi starter blueprint, usporedi s našim komplementarnim postom: Next.js + Supabase SaaS starter architecture.

# Namjerno “opinionated” struktura foldera i modula#

Cilj je da ownership bude očit: UI kod u Next.js, privilegirani kod u Edge Functions, shared logika u packageovima koji se čisto kompajliraju za oba runtimea.

Monorepo raspored#

PathSvrhaRuntime ograničenja
apps/webNext.js appNode.js ili Edge ovisno o ruti
supabase/functionsSupabase Edge FunctionsDeno runtime
packages/sharedČiste util funkcije i tipoviMora biti runtime-agnostic
packages/dbSQL migracije, tipizirani upitiNema runtimea, build-time tooling
packages/securityVerifikacija potpisa, helperi za hashiranjeAko je shared, mora izbjegavati Node-only API-je

Struktura Next.js aplikacije#

Koristi App Router i drži sve server-only module unutar jasne granice.

PathOdgovornostNapomene
apps/web/appRute i layoutiServer actions na razini rute drži blizu stranica
apps/web/app/(app)/actionsUI-driven Server ActionsDB zovi direktno, ili zovi Edge Functions kad treba
apps/web/app/apiRoute Handlers za client fetchPreferiraj za mobilne klijente i JSON endpointove
apps/web/lib/supabaseBrowser i server klijentiRazdvoji server-only od browser-safe modula
apps/web/lib/authHelperi za sesijuOvisi o tvom auth pristupu
apps/web/modules/*Domenski moduliSvaki modul posjeduje UI, actions i upite

Pattern domenskih modula#

Svaki domenski modul neka uključuje barem:

DatotekaSvrha
modules/billing/service.tsČista domenska logika, bez framework importa
modules/billing/actions.tsServer Actions za UI workflowe
modules/billing/queries.tsMetode pristupa podacima (RLS po defaultu)
modules/billing/validators.tsZod ili Valibot sheme
modules/billing/events.tsNazivi eventova i tipovi payloadova

Ovo se skalira bolje nego trpati sve u lib/ i kasnije pogađati ownership.

💡 Savjet: Ako funkciji treba Supabase service role key, ne bi smjela živjeti u apps/web. Stavi je u Edge Function i pozivaj je potpisanim zahtjevom.

Struktura Supabase Edge Functions#

Supabase Edge Functions rade na Deno. Izbjegavaj Node-specifične dependencyje i drži svaku funkciju malom i “single-purpose”.

PathSvrha
supabase/functions/_shared/env.tsParsiranje env varijabli i provjere
supabase/functions/_shared/supabase.tsKreiranje service role klijenta
supabase/functions/_shared/verify.tsUtilityji za verifikaciju potpisa
supabase/functions/stripe-webhook/index.tsStripe webhook handler
supabase/functions/auth-post-signup/index.tsProvisioning auth hook
supabase/functions/daily-rollup/index.tsZakazana agregacija

# Konkretni primjeri: što ide gdje#

Ovaj dio mapira česte SaaS zahtjeve na ispravno okruženje izvršavanja.

Primjer 1: Provisioning nakon signupa s Auth Hooks#

Problem: Na signup trebaš kreirati tenant workspace, seedati default podatke i dodati korisnika kao ownera.

Najbolje mjesto: Supabase Edge Function kao auth hook.

Zašto je bitno: provisioning treba privilegirane upise i mora biti konzistentan. Ako se osloniš na klijenta da kreira workspace, vidjet ćeš parcijalno stanje kad korisnici zatvore tab ili pukne mobilna mreža.

Što Edge Function radi:

  • Validira payload auth eventa
  • Kreira redak tenant workspacea
  • Ubacuje default postavke
  • Dodaje redak membershipa
TypeScript
// supabase/functions/auth-post-signup/index.ts
import { createClient } from "https://esm.sh/@supabase/supabase-js@2";
 
Deno.serve(async (req) => {
  const payload = await req.json();
  const userId = payload?.user?.id;
 
  if (!userId) return new Response("Missing user id", { status: 400 });
 
  const supabase = createClient(
    Deno.env.get("SUPABASE_URL") ?? "",
    Deno.env.get("SUPABASE_SERVICE_ROLE_KEY") ?? ""
  );
 
  const { data: workspace, error } = await supabase
    .from("workspaces")
    .insert({ owner_id: userId, name: "My Workspace" })
    .select()
    .single();
 
  if (error) return new Response(error.message, { status: 500 });
 
  await supabase.from("memberships").insert({
    user_id: userId,
    workspace_id: workspace.id,
    role: "owner",
  });
 
  return new Response("ok", { status: 200 });
});

Kada ovo ne raditi u Next.js: Ako se signup događa kroz Supabase Auth, a ne kroz tvoj Next.js code path, ne možeš pouzdano garantirati da će se Next.js hook izvršiti.

Primjer 2: Stripe webhookovi#

Problem: Stripe šalje evente poput invoice.paid i customer.subscription.updated. Moraš verificirati potpise i ažurirati billing stanje.

Najbolje mjesto: Supabase Edge Function.

Zašto je bitno: želiš stabilan endpoint neovisan o Next.js deploymentima i želiš ažurirati billing tablice s privilegiranim pristupom. Također želiš odgovoriti unutar provider timeouta, obično mjerljivih u sekundama, ne minutama.

Stripe verifikacija potpisa se oslanja na raw request body. U Edge Functions to kontroliraš konzistentno bez brige da će framework middleware izmijeniti payload.

TypeScript
// supabase/functions/stripe-webhook/index.ts
import Stripe from "https://esm.sh/stripe@15?target=deno";
 
Deno.serve(async (req) => {
  const sig = req.headers.get("stripe-signature");
  const secret = Deno.env.get("STRIPE_WEBHOOK_SECRET") ?? "";
  if (!sig) return new Response("Missing signature", { status: 400 });
 
  const raw = await req.text();
  const stripe = new Stripe(Deno.env.get("STRIPE_SECRET_KEY") ?? "", {
    apiVersion: "2024-06-20",
  });
 
  let event;
  try {
    event = stripe.webhooks.constructEvent(raw, sig, secret);
  } catch (_e) {
    return new Response("Invalid signature", { status: 400 });
  }
 
  // Update your DB using the service role client here.
  return new Response("ok", { status: 200 });
});

Problem: Ulogirani korisnici kliknu “Manage billing” kako bi dobili Stripe portal URL.

Najbolje mjesto: Next.js Server Action, opcionalno s pozivom Edge Functiona.

Zašto je bitno: ovo je UI-driven zahtjev vezan uz sesiju. Ako već imaš server pristup Stripeu u Next.js Node runtimeu, drži to blizu UI-ja.

Minimalni Server Action pattern:

TypeScript
// apps/web/app/(app)/settings/billing/actions.ts
"use server";
 
import { redirect } from "next/navigation";
 
export async function createBillingPortalAction() {
  // 1) Get the user and workspace from session
  // 2) Create Stripe portal session
  // 3) Redirect
  redirect("/settings/billing");
}

Ako želiš da svi Stripe credentialsi budu izolirani iz Next.js-a, pozovi Edge Function iz Server Actiona. Potpiši zahtjev shared secretnom i validiraj ga u funkciji.

ℹ️ Napomena: Dobar default je: Stripe webhookovi u Edge Functions, UI billing akcije u Next.js. UI billing akcije prebaci u Edge samo ako želiš jedinstven “blast radius” za Stripe tajne.

Primjer 4: Background zadaci i zakazani rollupovi#

Problem: Trebaš dnevni usage rollup po workspaceu, plus cleanup istečenih pozivnica.

Najbolje mjesto: Edge Function sa schedulerom za jednostavne jobove ili automation tooling za workflowe kojima trebaju retry, grananje i notifikacije.

Tipični rollup radi:

  • Agregira jučerašnje evente u tablicu usage_daily
  • Označava duplikate preko unique constrainta
  • Drži funkciju idempotentnom

Ako tvoj posao treba:

  • retry policyje po koraku
  • pozivanje više providera
  • slanje Slack alerta
  • human-in-the-loop odobravanja

tada je workflow alat bolji fit nego trpati sve u jednu funkciju.

# Pristup podacima: prvo RLS, service role samo kad treba#

U SaaS-u RLS nije opcionalan. To je primarna obrana od curenja tenant podataka.

Praktična pravila:

  • UI čitanja i upisi trebaju ići kroz korisničku sesiju i RLS.
  • Provider webhookovi često trebaju privilegirane upise jer nema korisničke sesije.
  • Cross-tenant administracija pripada u Edge Functions uz service role.

Jednostavan tenant pattern#

Većina B2B SaaS aplikacija koristi tablice poput:

  • workspaces
  • memberships s role
  • domenske tablice s workspace_id

Zatim RLS osigurava da korisnici mogu pristupati samo redovima za workspaces kojima pripadaju.

Ako želiš više patterna i čestih zamki, naš starter vodič to pokriva detaljno: Next.js + Supabase SaaS starter architecture.

# Kako Next.js sigurno komunicira sa Supabase Edge Functions#

Nemoj tretirati Edge Functions kao “internal-only” samo zato što su tvoje. Pretpostavi da će svaki javni URL biti pogođen skenerima i botovima.

Preporučeni patterni:

Pattern A: Provider-signed zahtjevi#

Za webhookove provider potpisuje payload. Ti ga verificiraš pa nastavljaš. Ovo je najbolji scenarij.

Pattern B: Shared-secret HMAC za interne pozive#

Kad Next.js zove Edge Function, uključi:

  • timestamp header
  • signature header
  • body

Zatim validiraj u funkciji i odbaci stare timestampe kako bi spriječio replay napade.

TypeScript
// apps/web/modules/security/sign.ts
import crypto from "crypto";
 
export function signPayload(secret: string, payload: string) {
  return crypto.createHmac("sha256", secret).update(payload).digest("hex");
}

Shared secret drži isključivo server-side. Nikad ga ne izlaži u client kodu.

⚠️ Upozorenje: Nikad ne pozivaj Edge Function koja koristi service role direktno iz browsera, čak i ako djeluje praktično. Proksiraj kroz Server Action ili API rutu i dodaj validaciju potpisa.

# Deployment razmatranja: Vercel vs Cloudflare#

Izbor deploymenta mijenja runtime defaultove i ograničenja. Najčešći produkcijski setup je:

  • Next.js na Vercelu
  • Supabase Edge Functions pod Supabaseom

Ali neki timovi deployaju Next.js na Cloudflare Pages ili Workers radi edge renderiranja. Evo što trebaš planirati.

Runtime i kompatibilnost#

TemaVercel Node.js runtimeVercel Edge runtimeCloudflare WorkersSupabase Edge Functions
Node API-jiPuniOgraničenoOgraničenoDeno, ograničena Node kompatibilnost
Cold startoviObično niskiVrlo niskiVrlo niskiNiski, globalno distribuirano
Najbolje zaStripe SDK, PDF-ovi, teške libovePersonalizacija, lagani API-jiEdge-first aplikacijeWebhookovi, hookovi, privilegirani DB ops
Česta zamkaVeliki serverless bundleoviKorištenje Node-only libovaNeusklađenosti Node modulaPretpostavka o dugotrajnom radu

Za detaljne trade-offove i migration “gotcha” situacije, vidi: Next.js Edge runtime vs Node.js runtime on Vercel and Cloudflare.

Environment varijable i tajne#

Praktične smjernice:

  • SUPABASE_SERVICE_ROLE_KEY stavi samo u environment za Supabase Edge Functions, ne u Next.js osim ako je apsolutno nužno.
  • U Next.js javne env varijable stavi samo:
    • NEXT_PUBLIC_SUPABASE_URL
    • NEXT_PUBLIC_SUPABASE_ANON_KEY
  • Tajne webhookova drži tamo gdje webhook živi. Stripe webhook secret pripada Edge Functionu koji ga prima.

Deployment workflow#

Pouzdan workflow za timove:

  1. 1
    Migracije baze deployaj prve
  2. 2
    Edge Functions deployaj druge
  3. 3
    Next.js aplikaciju deployaj treću

Time sprječavaš da Next.js zove endpointove ili tablice koje još ne postoje, i sprječavaš da webhookovi upisuju u tablice kojima nedostaju nove kolone.

Verzije i backward kompatibilnost#

Webhookovi mogu stići bilo kada, uključujući tijekom deploymenta. Tvoj webhook handler mora tolerirati stare oblike payloada u kratkom prozoru.

Dvije taktike koje smanjuju incidente:

  • DB promjene radi backward kompatibilnima barem kroz jedan deploy ciklus.
  • Novo ponašanje “gateaj” feature flagom spremljenim u DB, ne samo environment varijablama.

# Praktičan request flow: end-to-end primjer#

Razmotri tipičnu funkcionalnost “invite teammate”.

  • Korisnik klikne Invite u UI-ju.
  • Next.js Server Action validira email i ulogu.
  • Server Action ubacuje invite red pod RLS-om.
  • DB trigger ili zakazani job odrađuje cleanup isteka.
  • Automatizacija ili Edge Function šalje email preko providera.

Gdje slati email:

  • Ako email provider vraća webhooks, drži taj webhook u Edge Functions.
  • Ako ti trebaju retry i grananje, guraj u automatizaciju.
  • Ako je jednostavan “one-off”, možeš poslati direktno u Server Actionu s provider SDK-om, ali pazi na latenciju.

Čest kompromis:

  • Server Action upiše outbox_messages red.
  • Zakazana Edge Function obrađuje outbox i označi redove kao poslane. To ti daje retry i idempotenciju bez uvođenja punog queue sustava.

# Observability i obrada grešaka#

SaaS pouzdanost se najčešće gubi u pukotinama između sustava.

Minimalni observability checklist:

  • Logiraj ID-jeve webhook eventova i spremaj ih u tablicu s unique constraintom kako bi spriječio duplu obradu.
  • Prati retrye i zadnju poruku greške za background zadatke.
  • Emitiraj strukturirane logove iz Edge Functions s konzistentnim poljima poput event_type, workspace_id i request_id.

Konkretan pattern za idempotenciju:

  • stripe_events tablica s event_id unique
  • Handler radi: prvo insert event reda, ako je conflict onda vrati 200

Ovo sprječava double-charging i duplirani provisioning, posebno jer provideri rade retry na non-200 odgovore.

# Česte zamke u Next.js + Supabase Edge Functions arhitekturi#

  1. 1

    Korištenje service role ključa u Next.js route handlerima
    Radi dok se ne dogodi misconfig i ne izloži se. Privilegirane ključeve drži u Edge Functions.

  2. 2

    Preskakanje RLS-a jer Edge Functions mogu zaobići RLS
    RLS smanjuje količinu koda koju moraš auditirati. Bypass koristi samo kad je nužno.

  3. 3

    Dugotrajni posao u Edge Functions
    Edge Functions su odlične za kratkotrajni compute. Za teške jobove koristi worker ili automatizaciju.

  4. 4

    Tretiranje webhookova kao “samo još jedan API”
    Webhookovi trebaju verifikaciju potpisa nad raw bodyjem, idempotenciju i sigurne failure modove.

  5. 5

    Miješanje Node-only biblioteka u Edge runtimeove
    Odluku donosi po endpointu. Ako je biblioteka Node-only, stavi je u Node runtime rutu.

# Ključne poruke#

  • Koristi Supabase Edge Functions za endpointove prema providerima poput webhookova i auth hookova, te za privilegirane operacije koje traže service role key.
  • Koristi Next.js Server Actions za UI-driven upise i workflowe gdje RLS može provoditi autorizaciju i gdje ti koristi da je logika blizu React ruta.
  • Drži “opinionated” strukturu: domenski moduli u Next.js, shared čiste util funkcije u packageovima i male single-purpose Edge Functions s _shared helperima.
  • Deployaj redoslijedom: prvo migracije, zatim Edge Functions, pa Next.js, i drži webhook handlere idempotentnima kako bi preživjeli provider retrye.
  • Biraj runtime namjerno: Node runtime za teške SDK-ove, Edge runtime za lagane low-latency endpointove, a tajne drži u okruženju gdje se koriste.

# Zaključak#

Modernom SaaS backendu ne treba ogroman bespoke API sloj. Uz ispravnu Next.js + Supabase Edge Functions arhitekturu možeš zadržati UI workflowe jednostavnima kroz Server Actions, provider integracije robusnima kroz Edge Functions i prepustiti Postgres RLS-u da po defaultu provodi tenant granice.

Ako želiš da pregledamo tvoju trenutnu arhitekturu ili da ti pomognemo implementirati produkcijski spreman Next.js i Supabase SaaS temelj, kontaktiraj Samioda i mapirat ćemo tvoje domene, runtimeove i deployment pipeline u plan koji možeš pouzdano isporučiti.

FAQ

Share
A
Adrijan OmićevićOsnivač i senior developer

Osnivač i senior developer u Samiodi. 8+ godina iskustva u izradi React, Next.js, Flutter i n8n rješenja za klijente diljem Europe.

Trebate pomoć s projektom?

Gradimo prilagođena rješenja koristeći tehnologije iz ovog članka. Senior tim, fiksne cijene.