Running Self-Hosted Supabase on Low-Memory Servers

Learn how to optimize self-hosted Supabase for 2-4GB RAM VPS instances with Docker resource limits and service trimming.

Cover Image for Running Self-Hosted Supabase on Low-Memory Servers

Running self-hosted Supabase on a budget VPS is possible, but the default configuration assumes you have resources to spare. If you've tried spinning up Supabase on a 2GB or 4GB RAM server, you've probably seen containers crash with OOM errors—particularly the infamous logflare memory allocation failure. This guide shows you how to trim the fat and configure resource limits so Supabase runs reliably on constrained hardware.

The Problem: Supabase Default Resource Usage

A standard Supabase Docker Compose deployment includes approximately 12 containers. Out of the box, these services collectively want 4GB+ of RAM, with PostgreSQL and the analytics stack (Logflare/Vector) being the biggest consumers.

Here's what the default stack includes:

ServicePurposeTypical Memory
PostgreSQLDatabase500MB-2GB
KongAPI Gateway50-100MB
GoTrue (Auth)Authentication50-100MB
PostgRESTREST API50-100MB
RealtimeWebSocket subscriptions100-300MB
StorageFile storage API50-100MB
imgproxyImage transformations100-200MB
LogflareAnalytics500MB-1.8GB
VectorLog pipeline100-200MB
StudioDashboard200-400MB
Edge FunctionsServerless runtime150MB+
pg_metaDatabase metadata50MB

The analytics stack alone can consume 1.8GB on some deployments—that's nearly all of your RAM on a 2GB VPS.

Step 1: Disable Services You Don't Need

The fastest way to reduce memory usage is to remove services you're not using. For many projects, you can cut memory consumption from 4GB+ down to under 1GB by trimming optional features.

Identifying Non-Essential Services

Ask yourself which features you actually need:

Core services (keep these):

  • PostgreSQL (db)
  • Kong (API gateway)
  • GoTrue (auth)
  • PostgREST (rest)
  • pg_meta (meta)

Optional services (disable if unused):

  • Logflare + Vector: Analytics and logging. Unless you need the dashboard analytics, remove these first—they're the biggest memory hogs.
  • Realtime: Only needed for real-time subscriptions via WebSockets. Many apps don't use this.
  • Storage + imgproxy: Only needed if you're storing files through Supabase Storage.
  • Edge Functions (edge-runtime): Only needed if you're using Deno-based serverless functions.
  • Studio: You can manage your database with external tools like pgAdmin or DBeaver.

How to Disable Services

Edit your docker-compose.yml and comment out or remove the service blocks you don't need. Also remove any depends_on references to those services from other containers.

# Example: Comment out analytics services
# analytics:
#   image: supabase/logflare:...
#   ...

# vector:
#   image: timberio/vector:...
#   ...

After editing, restart the stack:

docker compose down && docker compose up -d

Memory Savings

A minimal Supabase setup (PostgreSQL, Kong, Auth, REST, pg_meta) can run in under 800MB of RAM. Adding Studio brings it to about 1.2GB. This is achievable on a 2GB VPS with room for the OS and some headroom.

Step 2: Set Docker Memory Limits

Even after trimming services, you should set explicit memory limits in Docker Compose. Without limits, a single container can consume all available RAM and crash your entire server.

Add resource constraints under each service's deploy section:

services:
  db:
    image: supabase/postgres:15.8.1.55
    deploy:
      resources:
        limits:
          memory: 1G
        reservations:
          memory: 512M
    # ... rest of config

  kong:
    deploy:
      resources:
        limits:
          memory: 256M
        reservations:
          memory: 128M

  auth:
    deploy:
      resources:
        limits:
          memory: 256M
        reservations:
          memory: 128M

  rest:
    deploy:
      resources:
        limits:
          memory: 256M
        reservations:
          memory: 128M

  studio:
    deploy:
      resources:
        limits:
          memory: 512M
        reservations:
          memory: 256M

2GB RAM Server (minimal setup):

  • db: 768MB limit
  • kong: 128MB limit
  • auth: 128MB limit
  • rest: 128MB limit
  • meta: 64MB limit
  • Total: ~1.2GB, leaving 800MB for OS

4GB RAM Server (standard setup):

  • db: 1.5GB limit
  • kong: 256MB limit
  • auth: 256MB limit
  • rest: 256MB limit
  • realtime: 256MB limit
  • storage: 256MB limit
  • studio: 512MB limit
  • Total: ~3.3GB, leaving 700MB for OS

Important: You must recreate containers for new limits to take effect. Running docker compose up -d alone won't apply memory limits to existing containers—use docker compose down && docker compose up -d.

Step 3: Tune PostgreSQL for Low Memory

The default PostgreSQL configuration is conservative, but you can optimize it further for memory-constrained environments.

Add these environment variables to your db service:

db:
  environment:
    # For 2GB RAM server
    POSTGRES_SHARED_BUFFERS: 256MB
    POSTGRES_EFFECTIVE_CACHE_SIZE: 512MB
    POSTGRES_MAINTENANCE_WORK_MEM: 64MB
    POSTGRES_WORK_MEM: 4MB
    POSTGRES_WAL_BUFFERS: 8MB
    POSTGRES_MAX_CONNECTIONS: 50

For a 4GB server with more services:

db:
  environment:
    POSTGRES_SHARED_BUFFERS: 512MB
    POSTGRES_EFFECTIVE_CACHE_SIZE: 1GB
    POSTGRES_MAINTENANCE_WORK_MEM: 128MB
    POSTGRES_WORK_MEM: 8MB
    POSTGRES_WAL_BUFFERS: 16MB
    POSTGRES_MAX_CONNECTIONS: 100

The most impactful setting is shared_buffers—this is memory PostgreSQL pre-allocates for caching data. The rule of thumb is 25% of available RAM, but on constrained systems you may need to go lower.

For more advanced PostgreSQL tuning, see our PostgreSQL performance tuning guide.

Step 4: Add Swap Space (Safety Net)

Even with careful tuning, memory usage can spike during peak loads or vacuum operations. Adding swap space provides a safety net that prevents hard crashes, though at a performance cost.

# Create 2GB swap file
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

# Make persistent
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

Monitor swap usage—if it consistently stays above 70%, your server is undersized for your workload and you should consider upgrading or further optimizing.

Step 5: Monitor Memory Usage

Set up basic monitoring to catch issues before they cause outages. You can check container memory usage with:

docker stats --no-stream

For continuous monitoring, consider setting up Prometheus and Grafana as described in our monitoring guide. This lets you track memory trends over time and set up alerts.

Key metrics to watch:

  • Container memory usage vs. limits
  • System swap usage
  • PostgreSQL shared buffer hit ratio (should be >99%)
  • OOM kill events in system logs

The Trade-offs

Running Supabase on minimal resources involves trade-offs you should understand:

What you lose by disabling services:

  • No analytics dashboard without Logflare/Vector
  • No real-time subscriptions without Realtime service
  • No file storage without Storage service
  • No edge functions without the runtime
  • Potentially slower image delivery without imgproxy

Performance considerations:

  • Lower PostgreSQL shared_buffers means more disk I/O
  • Fewer max connections limits concurrent users
  • Tight memory limits may cause container restarts during spikes

When to upgrade instead:

  • If swap usage is consistently high
  • If you need most of the optional services
  • If your database grows beyond a few GB
  • If you have more than a handful of concurrent users

For serious production workloads, check our VPS recommendations for providers that offer good value at 4-8GB RAM tiers.

How Supascale Helps

Supascale gives you a management dashboard for self-hosted Supabase that helps you make better decisions about resource allocation:

  • Selective service deployment: Only enable the services you need through a simple UI, automatically reducing your resource footprint
  • Automated backups: S3-compatible backup storage means you don't need to run additional backup containers
  • One-click restore: Test your setup on minimal resources knowing you can recover quickly
  • OAuth configuration: Configure auth providers through the UI instead of editing docker-compose files

The one-time pricing of $39.99 for unlimited projects means you can experiment with multiple configurations without worrying about ongoing costs.

Quick Reference: Minimal vs Standard Setup

ConfigurationRAM RequiredServicesBest For
Minimal2GBdb, kong, auth, rest, metaSide projects, dev/staging
Standard4GB+ studio, storage, realtimeProduction apps
Full8GB++ analytics, functions, imgproxyFull-featured production

Conclusion

Self-hosted Supabase can run on budget VPS instances if you're willing to trim optional services and set appropriate resource limits. Start minimal, monitor your usage, and add services back as needed. This approach lets you validate your project economics before committing to larger infrastructure.

The key steps:

  1. Disable analytics (Logflare/Vector) first—biggest memory savings
  2. Remove unused services (Realtime, Storage, Functions)
  3. Set explicit Docker memory limits
  4. Tune PostgreSQL for available RAM
  5. Add swap as a safety net
  6. Monitor and adjust

For most side projects and early-stage apps, a 4GB VPS with selective services is the sweet spot between cost and capability.

Further Reading