Selective Service Deployment for Self-Hosted Supabase: Only Run What You Need

Learn which Supabase services you actually need and how to disable unnecessary ones to reduce resource usage, costs, and complexity.

Cover Image for Selective Service Deployment for Self-Hosted Supabase: Only Run What You Need

When you deploy self-hosted Supabase using the default Docker Compose configuration, you get everything: PostgreSQL, Auth, Storage, Realtime, Edge Functions, Analytics, and more. That's 15+ containers running simultaneously, consuming memory, CPU cycles, and your attention.

But here's the thing—most applications don't need all of these services. If you're building a REST API that just needs a database and authentication, why run Realtime, imgproxy, and Analytics? That's wasted resources and unnecessary complexity.

This guide walks you through each Supabase service, explains what it does, and helps you decide which ones you actually need. Then we'll show you how to safely disable the rest.

Understanding the Supabase Service Stack

Before you start removing services, you need to understand what each one does. Here's the complete breakdown of a self-hosted Supabase deployment:

Core Services (Required)

These services form the foundation of Supabase. You cannot disable them without breaking core functionality:

PostgreSQL (supabase-db) The heart of Supabase. All your data lives here. Every other service depends on it.

  • Memory usage: ~350MB baseline
  • Always required: Yes

Kong (supabase-kong) API gateway that routes requests to the appropriate services. Handles authentication, rate limiting, and request routing.

  • Memory usage: ~100-200MB
  • Always required: Yes

GoTrue (supabase-auth) Authentication service. Handles signups, logins, OAuth, magic links, and session management.

  • Memory usage: ~50MB
  • Required if: You use Supabase Auth (most projects do)

PostgREST (supabase-rest) Automatically generates a REST API from your PostgreSQL schema. This is how your frontend talks to your database.

  • Memory usage: ~50MB
  • Required if: You use the Supabase client libraries or REST API

Supabase Studio (supabase-studio) The dashboard UI for managing your database, running queries, and viewing data.

  • Memory usage: ~200MB
  • Required if: You want a visual admin interface

Optional Services (Can Be Disabled)

These services provide additional functionality but aren't required for every application:

Realtime (supabase-realtime) Elixir server that broadcasts database changes to connected clients via WebSockets. Enables live subscriptions.

  • Memory usage: ~200-500MB
  • Disable if: You don't need real-time subscriptions or presence features

Storage (supabase-storage) RESTful API for file management with S3-compatible backend. Includes access control via RLS policies.

  • Memory usage: ~100MB
  • Disable if: You handle file uploads separately or don't need file storage

imgproxy (supabase-imgproxy) On-the-fly image transformation server. Resizes, crops, and optimizes images stored in Supabase Storage.

  • Memory usage: ~50-100MB
  • Disable if: You don't use image transformations or handle them elsewhere

Edge Functions (supabase-edge-functions) Deno-based serverless functions runtime. Runs TypeScript/JavaScript at the edge.

  • Memory usage: ~100-200MB
  • Disable if: You don't use Edge Functions or prefer traditional serverless (AWS Lambda, etc.)

Analytics/Logflare (supabase-analytics) Log aggregation and analytics platform. Stores and queries logs from all services.

  • Memory usage: ~500MB+
  • Disable if: You use external logging (Datadog, Grafana, etc.) or don't need log analytics

Meta (supabase-meta) Metadata service for schema introspection. Powers some Studio features.

  • Memory usage: ~50MB
  • Can sometimes be disabled if you don't use related Studio features

Vector (supabase-vector) Log collection agent. Ships logs to Analytics.

  • Memory usage: ~100MB
  • Disable if: You disable Analytics

Deciding What You Need: Common Scenarios

Here are practical examples based on real application types:

Scenario 1: REST API Backend

You need: PostgreSQL, Kong, GoTrue, PostgREST, Studio You can disable: Realtime, Storage, imgproxy, Edge Functions, Analytics

This is the most minimal useful deployment. You get a database, authentication, and auto-generated REST APIs. Perfect for traditional web apps and mobile backends that don't need real-time features.

Estimated memory savings: 800MB-1GB

Scenario 2: Real-time Application (Chat, Collaboration)

You need: PostgreSQL, Kong, GoTrue, PostgREST, Realtime, Studio You can disable: Storage, imgproxy, Edge Functions, Analytics

If your app relies on live updates—chat messages, collaborative editing, live dashboards—you need Realtime. Everything else is optional.

Estimated memory savings: 600-800MB

Scenario 3: Content Platform with Media

You need: PostgreSQL, Kong, GoTrue, PostgREST, Storage, imgproxy, Studio You can disable: Realtime, Edge Functions, Analytics

Building a CMS, image gallery, or any app with user-uploaded media? Keep Storage and imgproxy. The image transformation features are particularly useful for generating thumbnails and optimized formats on-the-fly.

Estimated memory savings: 300-500MB

You need: Everything except Analytics (usually)

Some applications genuinely need all the features. But even then, most self-hosters disable Analytics because they prefer external observability tools like Grafana or Datadog.

Estimated memory savings: 500MB+

How to Disable Services

There are two approaches to disabling services: manual Docker Compose editing or using a management tool like Supascale that handles this automatically.

Manual Approach: Editing Docker Compose

  1. Create a backup of your docker-compose.yml:
cp docker-compose.yml docker-compose.yml.backup
  1. Remove the service block for each service you want to disable. For example, to disable Realtime:
# Remove this entire block:
realtime:
  image: supabase/realtime:v2.x.x
  # ... all configuration
  1. Remove dependencies that reference the disabled service. Search for depends_on blocks that mention it:
# Before:
kong:
  depends_on:
    - realtime
    - storage
    
# After (if disabling realtime):
kong:
  depends_on:
    - storage
  1. Update Kong routes in your kong.yml to remove routes for disabled services. This prevents 502 errors when clients try to access disabled features.

  2. Restart your deployment:

docker compose down && docker compose up -d

The Easy Way: Supascale's Selective Deployment

If manual Docker Compose editing sounds tedious, that's because it is. One misconfigured dependency and your entire stack fails to start.

Supascale provides a UI for selective service deployment. When creating or editing a project, you simply toggle which services you want enabled:

  • ✅ Database (always on)
  • ✅ Auth
  • ✅ REST API
  • ⬜ Realtime
  • ⬜ Storage
  • ⬜ Edge Functions

The tool automatically handles dependencies, Kong routing, and environment variables. No YAML editing required.

This is particularly valuable when managing multiple Supabase projects on the same server—different projects can run different service combinations based on their actual needs.

Real-World Resource Savings

The Supabase community has shared actual resource usage from self-hosted deployments. Here's what a full deployment typically consumes:

ServiceMemory Usage
supabase-kong2.5GB
supabase-analytics525MB
supabase-db350MB
supabase-realtime210MB
supabase-studio200MB
supabase-storage100MB
supabase-edge-functions100MB
supabase-imgproxy75MB

A full deployment requires 4GB+ RAM just for baseline operation. But if you disable Analytics, Realtime, Storage, Edge Functions, and imgproxy, you're looking at roughly 3GB of savings.

This means you can run a functional Supabase instance on a 2GB VPS instead of needing 4GB+. At typical VPS pricing, that's a savings of $10-20/month—or $120-240/year.

For guidance on choosing the right server, see our VPS provider recommendations.

Common Pitfalls When Disabling Services

Pitfall 1: Client SDK Errors

The Supabase client libraries expect all features to be available. If you disable Realtime and then call supabase.channel(), your app will crash or hang.

Solution: Audit your codebase before disabling services. Search for:

  • realtime or channel( → Requires Realtime
  • storage.from → Requires Storage
  • functions.invoke → Requires Edge Functions

Pitfall 2: Broken Kong Routes

If Kong still has routes pointing to disabled services, API requests will return 502 errors.

Solution: Remove corresponding routes from kong.yml or use a tool that handles this automatically.

Pitfall 3: Missing Dependencies

Some services depend on others in non-obvious ways. For example, Studio uses Meta for schema introspection.

Solution: Test thoroughly after disabling services. Start with one service at a time and verify everything still works.

Pitfall 4: Storage RLS Without Storage

If you have Storage RLS policies in your database but disable the Storage service, migrations might fail or behave unexpectedly.

Solution: Remove Storage-related database objects if you permanently disable Storage.

Monitoring After Optimization

After disabling services, monitor your deployment to ensure everything works correctly:

  1. Check container health:
docker compose ps

All remaining containers should show "Up" status.

  1. Test critical paths:
  • Can users sign in?
  • Do database queries work?
  • Are the features you kept functional?
  1. Monitor resource usage:
docker stats

Verify memory usage has decreased as expected.

For comprehensive monitoring setup, see our observability guide.

When to Re-Enable Services

Your needs might change over time. Here are signs you should re-enable a service:

  • Re-enable Realtime when you add collaborative features, live notifications, or presence indicators
  • Re-enable Storage when you need user file uploads or media management
  • Re-enable Edge Functions when you need serverless compute without managing separate infrastructure
  • Re-enable Analytics when debugging production issues requires log analysis

The beauty of self-hosting is flexibility. You're not locked into any configuration.

Conclusion

Running all Supabase services by default is convenient for getting started, but inefficient for production. By understanding what each service does and disabling what you don't need, you can:

  • Reduce memory usage by 50-75%
  • Run on smaller, cheaper servers
  • Decrease attack surface
  • Simplify maintenance and updates

The manual approach works but requires careful Docker Compose editing. Tools like Supascale handle selective deployment automatically, letting you toggle services on and off without touching configuration files.

Start by auditing your application's actual Supabase usage. Then disable what you don't need. Your server (and your wallet) will thank you.


Further Reading