Skip to main content

Overview

Supabase is a unified platform built from multiple open-source components that work together seamlessly. Each component is independently powerful, but when combined, they provide a complete backend solution. Supabase Architecture Diagram
This architecture applies to both the hosted platform and self-hosted deployments. The core components remain the same.

Core Components

PostgreSQL Database

At the heart of Supabase is PostgreSQL - the world’s most advanced open-source relational database.

Features

  • ACID compliance for data integrity
  • Advanced data types (JSON, arrays, ranges)
  • Full-text search
  • Geospatial queries with PostGIS
  • Powerful indexing and query optimization

Extensions

  • pgvector for AI/embeddings
  • pg_cron for scheduled jobs
  • PostGIS for location data
  • pg_stat_statements for query analysis
  • And 50+ more extensions
Why PostgreSQL? PostgreSQL has over 30 years of active development and is trusted by organizations worldwide for:
  • Reliability and data integrity
  • Standards compliance
  • Extensibility
  • Active community and ecosystem
  • Battle-tested performance at scale
Example: Advanced Data Types
-- JSON columns for flexible schemas
CREATE TABLE products (
  id BIGINT PRIMARY KEY,
  name TEXT,
  metadata JSONB,  -- Fast JSON queries
  tags TEXT[],     -- Array of tags
  price_range NUMRANGE  -- Price ranges
);

-- Query JSON fields directly
SELECT * FROM products 
WHERE metadata->>'category' = 'electronics'
  AND tags @> ARRAY['featured'];

PostgREST

PostgREST automatically generates a RESTful API from your PostgreSQL database schema. How it works:
  1. PostgREST introspects your database schema
  2. Creates REST endpoints for each table and view
  3. Translates HTTP requests to SQL queries
  4. Respects Row Level Security policies
Request Flow: Example: Automatic API Generation
-- Create a table
CREATE TABLE articles (
  id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  title TEXT,
  content TEXT,
  published BOOLEAN DEFAULT false,
  created_at TIMESTAMPTZ DEFAULT NOW()
);
PostgREST automatically creates these endpoints:
# List all articles
curl 'https://your-project.supabase.co/rest/v1/articles' \
  -H "apikey: your-anon-key"
Advanced Queries: PostgREST supports complex queries through URL parameters:
// Filter, sort, and paginate
const { data } = await supabase
  .from('articles')
  .select('id, title, author:profiles(name, avatar)')
  .eq('published', true)
  .ilike('title', '%supabase%')
  .order('created_at', { ascending: false })
  .range(0, 9)  // Pagination

// Translates to efficient SQL with joins

GoTrue (Authentication)

GoTrue is a JWT-based authentication server that manages users and issues access tokens. Authentication Flow: Key Features:
  • Email/Password - Traditional authentication
  • Magic Links - Passwordless email login
  • Phone/SMS - Mobile-first authentication
  • Social OAuth - Google, GitHub, GitLab, Azure, Facebook, Twitter, Discord, and more
  • SAML SSO - Enterprise single sign-on (Enterprise plan)
JWT Structure: When a user signs in, they receive a JWT token:
{
  "aud": "authenticated",
  "exp": 1234567890,
  "sub": "user-uuid-here",
  "email": "user@example.com",
  "role": "authenticated",
  "user_metadata": {
    "full_name": "John Doe"
  }
}
This token is sent with every request, allowing PostgreSQL RLS policies to enforce user-specific access control. Example: Row Level Security with Auth
-- Only authenticated users can read profiles
CREATE POLICY "Profiles are viewable by authenticated users"
  ON profiles FOR SELECT
  TO authenticated
  USING (true);

-- Users can only update their own profile
CREATE POLICY "Users can update own profile"
  ON profiles FOR UPDATE
  TO authenticated
  USING (auth.uid() = id)
  WITH CHECK (auth.uid() = id);

-- Custom role-based access
CREATE POLICY "Admins can delete any profile"
  ON profiles FOR DELETE
  TO authenticated
  USING (
    auth.jwt() ->> 'role' = 'admin'
  );

Realtime

Realtime is an Elixir server that broadcasts database changes and enables presence and broadcast features. Three Modes of Operation:
Listen to INSERT, UPDATE, and DELETE operations:
// Subscribe to all changes on a table
const channel = supabase
  .channel('messages')
  .on(
    'postgres_changes',
    {
      event: '*',
      schema: 'public',
      table: 'messages'
    },
    (payload) => {
      console.log('Change received!', payload)
    }
  )
  .subscribe()
How it works:
  1. PostgreSQL publishes WAL (Write-Ahead Log) changes
  2. Realtime server listens to the replication slot
  3. Filters changes based on RLS policies
  4. Broadcasts to subscribed clients via WebSockets
Realtime respects Row Level Security! Users only receive updates for rows they have access to.
Architecture:
PostgreSQL WAL

Realtime Server (Elixir)

WebSocket Connections

Client Applications

Storage

Storage provides S3-compatible object storage with PostgreSQL-based permissions. Features:

Storage Capabilities

  • Large file uploads (up to 5GB per file)
  • Resumable uploads
  • Automatic image optimization
  • CDN distribution
  • Signed URLs for private files

Security

  • Row Level Security for file access
  • Bucket-level policies
  • File size and type restrictions
  • Virus scanning (Enterprise)
Example: Image Upload with RLS
// Create a storage bucket
const { data, error } = await supabase
  .storage
  .createBucket('avatars', {
    public: false,
    fileSizeLimit: 1024 * 1024 * 2 // 2MB
  })

// Upload a file
const file = event.target.files[0]
const { data, error } = await supabase
  .storage
  .from('avatars')
  .upload(`${userId}/${file.name}`, file)

// Get public URL (for public buckets)
const { data } = supabase
  .storage
  .from('avatars')
  .getPublicUrl(`${userId}/${file.name}`)

// Get signed URL (for private buckets)
const { data, error } = await supabase
  .storage
  .from('avatars')
  .createSignedUrl(`${userId}/${file.name}`, 60) // 60 seconds
Storage Policies:
-- Allow users to upload their own avatars
CREATE POLICY "Users can upload own avatar"
  ON storage.objects FOR INSERT
  TO authenticated
  WITH CHECK (
    bucket_id = 'avatars' AND
    (storage.foldername(name))[1] = auth.uid()::text
  );

-- Allow users to view all avatars
CREATE POLICY "Avatars are publicly accessible"
  ON storage.objects FOR SELECT
  TO public
  USING (bucket_id = 'avatars');

-- Allow users to delete their own avatars
CREATE POLICY "Users can delete own avatar"
  ON storage.objects FOR DELETE
  TO authenticated
  USING (
    bucket_id = 'avatars' AND
    (storage.foldername(name))[1] = auth.uid()::text
  );
Image Transformation: Automatic image optimization on-the-fly:
// Resize and optimize
const url = supabase
  .storage
  .from('avatars')
  .getPublicUrl('user.jpg', {
    transform: {
      width: 200,
      height: 200,
      resize: 'cover',
      quality: 80
    }
  })

Edge Functions

Edge Functions are server-side TypeScript functions that run on Deno at the edge, close to your users. Key Characteristics:
  • TypeScript/JavaScript - Familiar language and syntax
  • Deno runtime - Secure by default, modern APIs
  • Global distribution - Deploy to regions worldwide
  • Fast cold starts - Minimal latency
  • HTTP triggers - Invoke via HTTP requests
  • Cron triggers - Schedule periodic execution
Example: Send Welcome Email
// supabase/functions/send-welcome-email/index.ts
import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'

const RESEND_API_KEY = Deno.env.get('RESEND_API_KEY')

serve(async (req) => {
  try {
    // Get user from auth header
    const authHeader = req.headers.get('Authorization')!
    const supabase = createClient(
      Deno.env.get('SUPABASE_URL') ?? '',
      Deno.env.get('SUPABASE_ANON_KEY') ?? '',
      { global: { headers: { Authorization: authHeader } } }
    )
    
    const { data: { user } } = await supabase.auth.getUser()
    
    // Send email via Resend
    const res = await fetch('https://api.resend.com/emails', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${RESEND_API_KEY}`
      },
      body: JSON.stringify({
        from: 'noreply@yourapp.com',
        to: user.email,
        subject: 'Welcome to Our App!',
        html: `<h1>Welcome ${user.email}!</h1>`
      })
    })
    
    const data = await res.json()
    
    return new Response(
      JSON.stringify(data),
      { headers: { 'Content-Type': 'application/json' } }
    )
  } catch (error) {
    return new Response(
      JSON.stringify({ error: error.message }),
      { status: 500, headers: { 'Content-Type': 'application/json' } }
    )
  }
})
Deploy and invoke:
# Deploy
supabase functions deploy send-welcome-email

# Invoke from client
const { data, error } = await supabase.functions.invoke('send-welcome-email')
Use Cases:
  • Send emails or notifications
  • Process payments with Stripe
  • Generate PDFs or images
  • Call third-party APIs
  • Complex validation logic
  • Data aggregation and reporting
  • Webhooks from external services

pg_graphql

pg_graphql is a PostgreSQL extension that exposes a GraphQL API. Example: GraphQL Queries
// Query with the JavaScript client
const { data, error } = await supabase
  .graphql
  .query(`
    query GetPosts {
      postsCollection {
        edges {
          node {
            id
            title
            author {
              name
            }
            comments {
              edges {
                node {
                  content
                }
              }
            }
          }
        }
      }
    }
  `)
GraphQL is automatically generated from your database schema and respects Row Level Security.

Kong API Gateway

Kong sits in front of all services, providing:
  • Request routing - Direct requests to appropriate services
  • Rate limiting - Protect against abuse
  • API key validation - Verify authentication
  • CORS handling - Cross-origin request management
  • Request/response transformation - Modify requests as needed
Request Flow:
Client Request

Kong Gateway
  ├→ /rest/v1/*      → PostgREST
  ├→ /auth/v1/*      → GoTrue
  ├→ /storage/v1/*   → Storage API
  ├→ /realtime/v1/*  → Realtime Server
  └→ /functions/v1/* → Edge Functions

postgres-meta

postgres-meta provides a RESTful API for managing PostgreSQL:
  • Fetch tables, columns, and relationships
  • Create and modify schemas
  • Manage roles and permissions
  • Run queries
  • View database statistics
This powers the Supabase Studio interface.

Studio Dashboard

Supabase Studio is the web-based dashboard that provides:

Table Editor

Visual interface to browse and edit data, manage relationships, and view table schemas

SQL Editor

Write and execute SQL queries with autocomplete and saved snippets

Auth Management

Manage users, configure providers, and customize email templates

Storage Browser

Browse buckets, upload files, and manage storage policies

API Documentation

Auto-generated API documentation based on your schema

Database Monitoring

View query performance, connection pools, and resource usage

Request Lifecycle

Let’s trace a typical request through the Supabase stack:
1

Client makes request

User application sends a request to query todos:
const { data } = await supabase
  .from('todos')
  .select('*')
  .eq('user_id', userId)
2

Kong receives request

Kong validates the API key and routes to PostgREST at /rest/v1/todos
3

PostgREST processes

  • Parses the request into SQL
  • Extracts JWT from headers
  • Sets PostgreSQL session variables (request.jwt.claims)
4

PostgreSQL executes query

  • Runs the SQL query
  • Evaluates Row Level Security policies using JWT claims
  • Returns only rows the user has access to
SELECT * FROM todos
WHERE user_id = $1
  AND ( -- RLS policy check
    auth.uid() = user_id
  )
5

Response returned

  • PostgreSQL returns filtered results
  • PostgREST formats as JSON
  • Kong sends response to client
  • Total round trip: ~50-100ms

Deployment Architecture

Hosted Platform

When using supabase.com:
Global CDN (Cloudflare)

Load Balancer

┌─────────────────────────┐
│   Your Project          │
│  ┌──────────────────┐   │
│  │ Kong Gateway     │   │
│  └────────┬─────────┘   │
│           │              │
│  ┌────────┴─────────┐   │
│  │ Service Layer    │   │
│  │ • PostgREST      │   │
│  │ • GoTrue         │   │
│  │ • Realtime       │   │
│  │ • Storage        │   │
│  │ • Functions      │   │
│  └────────┬─────────┘   │
│           │              │
│  ┌────────┴─────────┐   │
│  │ PostgreSQL       │   │
│  │ (Dedicated)      │   │
│  └──────────────────┘   │
└─────────────────────────┘
Benefits:
  • Automatic scaling
  • Global distribution
  • Managed backups
  • Monitoring and alerting
  • No operational overhead

Self-Hosted

Using Docker Compose:
services:
  kong:
    image: kong:latest
    ports:
      - "8000:8000"
  
  postgres:
    image: supabase/postgres:latest
    volumes:
      - postgres-data:/var/lib/postgresql/data
  
  auth:
    image: supabase/gotrue:latest
  
  rest:
    image: postgrest/postgrest:latest
  
  realtime:
    image: supabase/realtime:latest
  
  storage:
    image: supabase/storage-api:latest
  
  studio:
    image: supabase/studio:latest
    ports:
      - "3000:3000"
Benefits:
  • Full control
  • Deploy anywhere
  • No vendor lock-in
  • Custom configurations

Security Architecture

Multi-Layer Security

  • TLS/SSL - All traffic encrypted in transit
  • DDoS protection - Cloudflare protection on hosted platform
  • Network isolation - Services in private networks

API Keys

Supabase provides two main keys:
  • Safe to use in browsers and mobile apps
  • Has limited permissions
  • Used with user JWT for authenticated requests
  • RLS policies protect data
const supabase = createClient(url, ANON_KEY)
Critical: Never commit service_role keys to version control or use them in client applications. This key has unrestricted access to your database.

Scalability

Supabase components are designed to scale:

Horizontal Scaling

  • PostgREST - Stateless, can run multiple instances
  • GoTrue - Scales horizontally with load balancing
  • Realtime - Distributed across multiple nodes
  • Storage - S3-compatible, infinitely scalable
  • Edge Functions - Automatically scaled and distributed

Database Scaling

Increase compute resources:
  • More CPU cores
  • More RAM
  • Faster storage (NVMe SSDs)
Hosted platform supports up to:
  • 64 CPU cores
  • 256 GB RAM
  • Dedicated resources

Monitoring and Observability

Built-in Monitoring

Supabase provides comprehensive monitoring:
  • Query Performance - Slow query logs and analysis
  • Resource Usage - CPU, memory, disk, and network
  • API Analytics - Request rates, response times, errors
  • Realtime Connections - Active connections and channels
  • Storage Metrics - Bandwidth and storage usage

Logging

Collect logs from all components:
  • PostgreSQL logs - Query logs, error logs
  • API logs - Request/response logs
  • Edge Function logs - Console output and errors
  • Auth logs - Sign-in attempts and failures
Hosted platform integrates with:
  • Logflare for log management
  • Webhook destinations
  • Custom integrations

Next Steps

Now that you understand Supabase architecture:

Database Guide

Deep dive into PostgreSQL features and best practices

Auth Guide

Learn advanced authentication patterns

Realtime Guide

Build real-time collaborative features

Self-Hosting

Deploy Supabase on your infrastructure