Docker Container Resource Tuning for Self-Hosted Supabase

Optimize memory, CPU, and resource limits for each Supabase container to maximize performance on your self-hosted deployment.

Cover Image for Docker Container Resource Tuning for Self-Hosted Supabase

Running self-hosted Supabase means managing over a dozen Docker containers, each with different resource demands. Without proper tuning, Kong might consume 2GB of RAM while Auth barely uses 10MB. Your VPS could be starving critical services while others sit idle with excess resources.

This guide walks you through optimizing each Supabase container for production workloads—covering memory limits, CPU allocation, and the specific tuning each service needs.

Understanding Supabase's Container Architecture

Before tuning, you need to understand what you're running. A standard self-hosted Supabase deployment includes:

  • supabase-db: PostgreSQL database (the core)
  • supabase-rest: PostgREST API server
  • supabase-auth: GoTrue authentication service
  • supabase-realtime: Phoenix-based WebSocket server
  • supabase-storage: File storage API
  • supabase-kong: API gateway (often the memory hog)
  • supabase-studio: Admin dashboard
  • supabase-meta: Metadata service
  • supabase-analytics: Logflare analytics (optional as of June 2026)
  • supabase-vector: Log collection (optional)
  • supabase-edge-functions: Deno runtime

Each service has fundamentally different resource characteristics. PostgreSQL wants RAM for shared buffers. Realtime scales with WebSocket connections. Kong can balloon without limits. Understanding these patterns is essential for effective tuning.

Baseline Resource Requirements

According to community discussions and production deployments, here's typical memory usage for an idle Supabase stack:

ContainerTypical MemoryCPU Pattern
supabase-db350-500MBSpiky under queries
supabase-kong200MB-2.5GBConsistent
supabase-analytics400-600MBModerate
supabase-realtime150-300MBScales with connections
supabase-rest80-150MBScales with requests
supabase-studio60-100MBLow
supabase-storage30-50MBLow
supabase-auth8-20MBLow
supabase-meta40-70MBLow
supabase-edge-functions20-50MBScales with invocations

The total baseline sits around 1.5-4GB depending on configuration. For production, plan for at least 4GB RAM with headroom for spikes.

Setting Docker Resource Limits

Docker Compose supports resource limits through the deploy key. Add these to your docker-compose.yml:

services:
  db:
    image: supabase/postgres:15.1.1.78
    deploy:
      resources:
        limits:
          memory: 1G
          cpus: '2.0'
        reservations:
          memory: 512M
          cpus: '0.5'

Key concepts:

  • limits: Hard caps—container gets killed if exceeded
  • reservations: Guaranteed minimum resources
  • memory: RAM limit (supports K, M, G suffixes)
  • cpus: CPU cores (1.0 = one full core)

For limits to work with docker compose up, you need to either:

  1. Use Docker Swarm mode (docker stack deploy)
  2. Or add --compatibility flag: docker compose --compatibility up -d

Service-by-Service Tuning Guide

PostgreSQL (supabase-db)

PostgreSQL is where most tuning effort pays off. The container's memory usage is governed by PostgreSQL's internal configuration, not just Docker limits.

db:
  deploy:
    resources:
      limits:
        memory: 2G
        cpus: '2.0'
      reservations:
        memory: 1G
        cpus: '1.0'
  environment:
    - POSTGRES_INITDB_ARGS=--data-checksums

Inside the container, tune these PostgreSQL parameters via environment variables or by modifying the configuration:

shared_buffers = 512MB          # 25% of available RAM
effective_cache_size = 1536MB   # 75% of available RAM  
work_mem = 16MB                 # Per-operation memory
maintenance_work_mem = 128MB    # For VACUUM, CREATE INDEX
max_connections = 100           # Adjust based on pool size

For detailed PostgreSQL tuning, see our PostgreSQL performance tuning guide.

Kong API Gateway (supabase-kong)

Kong is often the biggest memory consumer. It loads all routes and plugins into memory, and without limits, it can grow unbounded.

kong:
  deploy:
    resources:
      limits:
        memory: 512M
        cpus: '1.0'
      reservations:
        memory: 256M
        cpus: '0.25'
  environment:
    - KONG_MEM_CACHE_SIZE=64m
    - KONG_NGINX_WORKER_PROCESSES=2

Kong-specific optimizations:

  • Reduce nginx_worker_processes from auto to a fixed number
  • Set mem_cache_size explicitly rather than letting it auto-scale
  • Consider replacing Kong with Caddy or Traefik if memory is critical—some users report saving hundreds of MB of RAM

Realtime Server

Memory scales linearly with WebSocket connections. Plan for roughly 1KB per connection plus base overhead.

realtime:
  deploy:
    resources:
      limits:
        memory: 512M
        cpus: '1.0'
      reservations:
        memory: 128M
        cpus: '0.25'
  environment:
    - MAX_HEADER_LENGTH=8192
    - REPLICATION_MODE=RLS

For applications with thousands of concurrent connections, see our Realtime configuration guide.

PostgREST (supabase-rest)

PostgREST maintains a connection pool to PostgreSQL. Memory usage correlates with concurrent API requests.

rest:
  deploy:
    resources:
      limits:
        memory: 256M
        cpus: '1.0'
      reservations:
        memory: 64M
        cpus: '0.25'
  environment:
    - PGRST_DB_POOL=20
    - PGRST_DB_POOL_ACQUISITION_TIMEOUT=10

Lower PGRST_DB_POOL if you're running into connection limits. Each pool connection consumes database resources.

Auth Service (GoTrue)

Auth is lightweight but handles critical authentication flows. Don't starve it.

auth:
  deploy:
    resources:
      limits:
        memory: 128M
        cpus: '0.5'
      reservations:
        memory: 32M
        cpus: '0.1'

Storage API

Memory usage depends on concurrent uploads and file sizes. For large file uploads, allocate more.

storage:
  deploy:
    resources:
      limits:
        memory: 256M
        cpus: '0.5'
      reservations:
        memory: 64M
        cpus: '0.1'
  environment:
    - FILE_SIZE_LIMIT=52428800
    - UPLOAD_TEMP_PATH=/tmp/uploads

Analytics and Vector (Optional)

As of June 2026, these services are opt-in. If you don't need the Logs Explorer in Studio, skip them entirely:

# Remove or comment out analytics and vector services
# analytics:
#   ...
# vector:
#   ...

This alone can save 500MB-1GB of RAM.

Studio Dashboard

Studio is a Next.js application. It's not needed for production API workloads—consider running it separately or only during development.

studio:
  deploy:
    resources:
      limits:
        memory: 256M
        cpus: '0.5'
      reservations:
        memory: 64M
        cpus: '0.1'

Complete Production Configuration

Here's a consolidated example for a 4GB VPS:

version: '3.8'

services:
  db:
    deploy:
      resources:
        limits:
          memory: 1536M
          cpus: '2.0'
        reservations:
          memory: 768M
    # ... rest of db config

  kong:
    deploy:
      resources:
        limits:
          memory: 384M
          cpus: '0.5'
        reservations:
          memory: 192M
    # ... rest of kong config

  rest:
    deploy:
      resources:
        limits:
          memory: 192M
          cpus: '0.5'
        reservations:
          memory: 64M
    # ... rest config

  realtime:
    deploy:
      resources:
        limits:
          memory: 384M
          cpus: '0.5'
        reservations:
          memory: 128M
    # ... realtime config

  auth:
    deploy:
      resources:
        limits:
          memory: 96M
          cpus: '0.25'
        reservations:
          memory: 32M
    # ... auth config

  storage:
    deploy:
      resources:
        limits:
          memory: 192M
          cpus: '0.25'
        reservations:
          memory: 48M
    # ... storage config

  studio:
    deploy:
      resources:
        limits:
          memory: 192M
          cpus: '0.25'
        reservations:
          memory: 64M
    # ... studio config

  meta:
    deploy:
      resources:
        limits:
          memory: 96M
          cpus: '0.25'
        reservations:
          memory: 32M
    # ... meta config

This allocates roughly 3GB to containers, leaving 1GB for the OS, Docker daemon, and spikes.

Monitoring Resource Usage

After deploying limits, monitor actual usage:

# Real-time container stats
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}"

# Check for OOM kills
docker inspect --format='{{.State.OOMKilled}}' <container_name>

# View resource limits
docker inspect --format='{{.HostConfig.Memory}}' <container_name>

For production monitoring, integrate with Prometheus and Grafana.

Warning Signs and Troubleshooting

Container keeps restarting:

  • Check docker logs <container> for OOM messages
  • Increase memory limit or investigate memory leaks
  • Verify reservations don't exceed host capacity

Swap usage climbing:

  • Add more RAM or reduce container limits
  • Swap above 70% indicates resource starvation

Kong consuming excessive memory:

  • Set explicit KONG_MEM_CACHE_SIZE
  • Reduce worker processes
  • Consider alternative reverse proxies

Database performance degraded:

When to Scale Up

Resource limits help on constrained hardware, but there's a floor. If you're consistently hitting limits across multiple services, it's time to:

  1. Add RAM first—most Supabase services are memory-bound
  2. Add CPU second—only matters under high concurrent load
  3. Consider horizontal scaling for Realtime if you have thousands of WebSocket connections

For VPS recommendations, see our guide on best VPS providers for self-hosted Supabase.

Conclusion

Proper container resource tuning transforms a struggling self-hosted Supabase into a stable production system. Start with the baseline recommendations, monitor actual usage, and adjust based on your workload patterns.

The key insights:

  • PostgreSQL needs the most memory—don't skimp
  • Kong can be a memory hog—set explicit limits
  • Analytics/Vector are optional as of June 2026—skip them to save resources
  • Always leave headroom for the OS and spikes
  • Monitor before and after changes to validate improvements

With Supascale, you get a streamlined management interface that handles deployment complexity, letting you focus on building rather than container orchestration. But whether you manage containers manually or use a platform, understanding these resource patterns helps you make informed scaling decisions.


Further Reading