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:
| Service | Purpose | Typical Memory |
|---|---|---|
| PostgreSQL | Database | 500MB-2GB |
| Kong | API Gateway | 50-100MB |
| GoTrue (Auth) | Authentication | 50-100MB |
| PostgREST | REST API | 50-100MB |
| Realtime | WebSocket subscriptions | 100-300MB |
| Storage | File storage API | 50-100MB |
| imgproxy | Image transformations | 100-200MB |
| Logflare | Analytics | 500MB-1.8GB |
| Vector | Log pipeline | 100-200MB |
| Studio | Dashboard | 200-400MB |
| Edge Functions | Serverless runtime | 150MB+ |
| pg_meta | Database metadata | 50MB |
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
Recommended Limits by Server Size
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_buffersmeans 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
| Configuration | RAM Required | Services | Best For |
|---|---|---|---|
| Minimal | 2GB | db, kong, auth, rest, meta | Side projects, dev/staging |
| Standard | 4GB | + studio, storage, realtime | Production apps |
| Full | 8GB+ | + analytics, functions, imgproxy | Full-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:
- Disable analytics (Logflare/Vector) first—biggest memory savings
- Remove unused services (Realtime, Storage, Functions)
- Set explicit Docker memory limits
- Tune PostgreSQL for available RAM
- Add swap as a safety net
- 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.
