Supabase has emerged as one of the most popular open-source Firebase alternatives, combining PostgreSQL, authentication, storage, realtime functionality, and APIs into a single backend platform. The managed cloud offering is convenient, but infrastructure costs can increase as applications grow and consume more database resources, storage, bandwidth, and compute.
Self-hosting Supabase on AWS EC2 with Docker Compose gives developers much greater control over the infrastructure. Instead of paying for an increasingly expensive managed backend tier, you can run the Supabase stack on your own AWS server and scale the infrastructure according to your application's actual requirements.
This guide explains how to deploy Supabase on an AWS EC2 instance using Docker, configure the server for production, secure the deployment, configure backups, monitor resources, and understand the real costs involved. The example uses an EC2 t3.medium instance as a starting point, but the correct server size depends on your workload, database queries, concurrent connections, storage requirements, and traffic.
Supabase provides many of the backend capabilities that modern web and mobile applications need. Instead of building authentication, database APIs, file storage, and realtime functionality independently, developers can use Supabase as a unified backend platform.
The managed version is attractive because infrastructure operations are handled for you. However, managed infrastructure can become expensive when an application begins generating significant database traffic or storage usage. Self-hosting allows you to choose your own compute resources and control how the infrastructure is configured.
AWS EC2 is particularly useful because it provides flexible virtual machines with different CPU, memory, storage, and networking configurations. You can begin with a relatively inexpensive instance and upgrade it when monitoring shows that additional resources are required.
There is an important trade-off, however. Self-hosting does not make infrastructure management disappear. You become responsible for operating system updates, Docker updates, security configuration, backups, monitoring, SSL certificates, database maintenance, and disaster recovery.
For developers who already have DevOps experience or want complete control over their infrastructure, this trade-off can be worthwhile.
For a small production application or initial deployment, an AWS EC2 t3.medium can provide a useful starting point. It offers a combination of CPU and memory that can handle considerably more traffic than a very small development instance.
However, server capacity should never be estimated purely from the number of registered or concurrent users. Ten thousand users do not necessarily generate the same amount of traffic. An application where users make occasional database requests can require dramatically fewer resources than an application performing continuous realtime queries, large database searches, file uploads, and complex joins.
For this reason, treat a t3.medium as a starting configuration rather than a guaranteed capacity target.
When creating the instance, select Ubuntu 24.04 LTS and attach a gp3 EBS volume. A 30GB volume can be sufficient for an initial deployment, but database growth, Docker images, logs, uploaded files, and backups can consume disk space faster than expected.
For production workloads, monitor disk utilization carefully and expand the volume before it becomes full. Running out of disk space can cause database failures and container instability.
The EC2 security group acts as a network-level firewall. Only expose the ports that are actually required by the deployment.
For a production Supabase server, HTTP and HTTPS traffic normally need to be available publicly. SSH is required for server administration, but access to port 22 should ideally be restricted to trusted IP addresses instead of allowing SSH connections from the entire internet.
A typical configuration includes:
During initial development you may temporarily expose another port for testing, but unnecessary public ports should be removed before production. Docker services should generally communicate internally through the Docker network rather than exposing every service directly to the internet.
After launching the EC2 instance, connect to it using SSH. The exact command depends on the key pair and public IP address assigned to the instance.
ssh -i your-key.pem ubuntu@YOUR_EC2_IP
Once connected, update the operating system packages before installing additional software:
sudo apt update
sudo apt upgrade -y
Keeping the operating system updated is an important part of production security. Security patches should be applied regularly rather than allowing the server to run an outdated Ubuntu installation indefinitely.
Supabase's self-hosted deployment uses Docker containers to run the different services that make up the platform. Install Docker using the official Docker installation process for your Ubuntu release.
After installation, verify that Docker is available:
docker --version
docker compose version
Docker Compose makes it possible to define and manage multiple related services using a single configuration. Instead of manually starting each Supabase component, Compose can start the complete stack and connect the services through their internal Docker network.
Supabase provides a self-hosted Docker configuration that can be used as the foundation for an EC2 deployment. Clone the repository onto the server:
git clone --depth 1 https://github.com/supabase/supabase
cd supabase/docker
Copy the example environment file:
cp .env.example .env
The environment file controls important configuration values used by the Supabase services. Before starting the containers, carefully review the configuration and replace all development or example credentials with strong production values.
Security secrets are one of the most important parts of a self-hosted Supabase deployment. Never deploy publicly documented example credentials or weak passwords.
Generate unique values for your database password, JWT-related secrets, API credentials, dashboard credentials, and other sensitive configuration values required by your deployment.
Production secrets should not be committed to Git repositories. The .env file should be protected on the server and excluded from source control.
If you operate a larger production environment, consider using a dedicated secrets-management solution rather than manually storing sensitive values on the server.
After the environment configuration has been reviewed, start the Supabase services in detached mode:
docker compose up -d
The first startup may take several minutes because Docker needs to download the required container images and initialize the services.
Check the status of the containers:
docker compose ps
All required services should reach their expected running or healthy state. If something fails, inspect the logs rather than repeatedly restarting the entire server.
docker compose logs --tail=100
You can also inspect the logs of an individual service when diagnosing a specific problem. This is useful for identifying invalid environment variables, database connection problems, missing configuration, port conflicts, or resource exhaustion.
A production deployment should use a domain or subdomain rather than exposing the Supabase server directly through an IP address.
For example, you could create a subdomain such as supabase.example.com or use a dedicated API hostname for your application.
Create a DNS record pointing the hostname to the EC2 instance's public IP address. Using an Elastic IP is preferable to relying on a dynamically assigned public IP because it provides a stable address that remains associated with the server when the instance is restarted.
Once DNS has propagated, verify that the hostname resolves correctly before configuring HTTPS.
HTTPS should be considered mandatory for a production Supabase deployment. Authentication tokens, cookies, API requests, and application data should not be transmitted over an unsecured HTTP connection.
A reverse proxy such as Nginx can sit in front of the Docker services and handle TLS termination. The proxy receives HTTPS requests on port 443 and forwards them internally to the appropriate Supabase service.
Let's Encrypt can be used to obtain a trusted TLS certificate. Certificate renewal should be automated so that the server does not unexpectedly become unavailable because of an expired certificate.
After HTTPS is configured, redirect HTTP traffic to HTTPS wherever appropriate. This ensures that users consistently access the application through an encrypted connection.
One of the most common mistakes when deploying Docker applications is exposing every container port directly to the internet. This increases the attack surface and makes the architecture unnecessarily difficult to secure.
Only services that genuinely require public access should be reachable from the internet. Internal services should communicate through Docker's private network.
This is particularly important for database services. PostgreSQL should not be exposed publicly simply because the application needs to communicate with it. The application and database can communicate over the internal Docker network.
PostgreSQL is the core database behind Supabase, so database performance has a major effect on the entire platform.
Before increasing the EC2 instance size, investigate inefficient queries. Missing indexes, unnecessary joins, large result sets, and poorly designed filters can consume significant CPU and memory.
Frequently queried columns should have appropriate indexes, but avoid adding indexes blindly. Every additional index consumes storage and can increase the cost of write operations.
Connection management is also important. Applications that create excessive PostgreSQL connections can exhaust available resources even when CPU utilization appears relatively low.
Use appropriate connection pooling and monitor active database connections. A well-configured connection strategy can allow a relatively modest EC2 instance to support significantly more application traffic.
Supabase Storage allows applications to upload and manage files. However, storing large amounts of user-generated content directly on the EC2 root volume can create operational problems.
As the application grows, storage requirements can increase quickly because of images, videos, documents, and other user uploads.
Consider separating large object storage from the primary application server. S3-compatible object storage can provide scalable storage without forcing the EC2 root volume to grow continuously.
If local storage is used, monitor disk capacity and implement a clear retention policy. Never allow logs, uploads, Docker images, or database files to consume the entire disk.
Backups are one of the biggest responsibilities when self-hosting Supabase. A production database should never depend on a single EC2 instance.
Configure automated PostgreSQL backups and store them outside the primary server. Amazon S3 is a common destination because backups can be retained independently of the EC2 instance.
Do not consider the backup strategy complete until restoration has been tested. A backup file that cannot be restored during an emergency provides little practical protection.
Schedule periodic recovery tests. Restore a backup into a separate environment and verify that the database and application can operate correctly.
Self-hosted infrastructure requires continuous monitoring. At minimum, monitor CPU usage, memory usage, disk utilization, network traffic, Docker container health, and database connections.
Docker provides a convenient way to inspect container resource consumption:
docker stats
AWS CloudWatch can provide additional EC2 monitoring and alerting. Configure notifications for conditions such as sustained high CPU utilization, low disk space, and other infrastructure problems.
Monitoring should help you identify trends before they become outages. For example, a disk that grows by several gigabytes every week can be addressed proactively instead of waiting until the filesystem reaches 100% capacity.
A single EC2 instance is a good starting point for many projects, but it should not be considered the final architecture for every production system.
If monitoring shows consistently high CPU or memory utilization, first determine what is causing the resource consumption. Optimizing database queries and application behavior can sometimes provide more benefit than simply purchasing a larger server.
If optimization is no longer sufficient, you can vertically scale the EC2 instance to a configuration with more CPU and memory.
For larger applications, the architecture can eventually evolve into multiple services and multiple instances. Database workloads, application services, storage, and monitoring can be separated according to the requirements of the application.
High-availability architectures may also use multiple availability zones, load balancers, replicated databases, external object storage, and automated infrastructure deployment. These approaches provide stronger resilience but introduce additional complexity and costs.
A self-hosted Supabase deployment should be treated like any other production internet-facing server. Security should be considered at several layers rather than relying on a single firewall rule.
The cost advantage of self-hosting depends heavily on how much infrastructure your application actually consumes. The EC2 instance is only one component of the total cost.
| Resource | Self-Hosted | Managed Pro |
|---|---|---|
| Compute (t3.medium) | $30 | $200 |
| Storage (30GB gp3) | $6 | Included |
| Bandwidth (500GB) | $10 | $50+ overage |
| Total | $46/month | $250+/month |
These numbers are illustrative and should not be treated as fixed AWS or Supabase pricing. AWS costs vary by region, instance pricing model, EBS storage usage, outbound bandwidth, backup storage, and other infrastructure requirements.
You should calculate your own monthly cost using your expected traffic and storage requirements. AWS pricing can also change, so verify current prices for the region where you plan to deploy.
The decision between self-hosting and using managed Supabase is primarily a trade-off between control and operational simplicity.
Managed Supabase reduces the amount of infrastructure work required from your team. You do not need to manually maintain the underlying server, manage the operating system, or build the entire backup and monitoring strategy yourself.
Self-hosting provides more control. You decide where the workload runs, how much compute is available, how networking is configured, and how the infrastructure integrates with the rest of your AWS environment.
For developers building small projects, managed infrastructure can be worth the convenience. For teams with DevOps experience, predictable workloads, or strict infrastructure requirements, self-hosting may provide better control over long-term infrastructure costs.
Before sending real production traffic to your self-hosted Supabase installation, verify the following checklist:
One common mistake is treating the EC2 server as a one-time setup. Production infrastructure requires ongoing maintenance. Security patches, Docker image updates, backups, monitoring, and capacity planning should all become part of the normal operating process.
Another mistake is focusing only on CPU usage. PostgreSQL performance can be limited by memory, disk I/O, connection counts, or inefficient queries even when CPU utilization is moderate.
Running out of disk space is another frequent problem. Docker images, container logs, database files, backups, and uploaded files can gradually consume storage. Disk monitoring and cleanup procedures should therefore be configured from the beginning.
Finally, never assume that a successful deployment automatically means the infrastructure is production-ready. A production system must also have security controls, backups, monitoring, recovery procedures, and a strategy for handling increased traffic.
Self-hosting Supabase on AWS EC2 with Docker provides a powerful alternative to relying entirely on a managed backend platform. You can run PostgreSQL, authentication, APIs, storage, and realtime capabilities under your own infrastructure while retaining the developer experience that makes Supabase attractive.
The biggest benefit is control. You decide how the infrastructure is deployed, how it is secured, how it is monitored, and when it should be scaled. For applications with predictable workloads, this can also make infrastructure costs easier to understand and manage.
However, self-hosting should not be viewed as a completely free alternative to managed Supabase. The infrastructure still has costs, and the operational responsibility moves to you. Backups, security updates, monitoring, SSL, database maintenance, and disaster recovery all become part of your responsibility.
A sensible approach is to start with a right-sized EC2 instance, deploy Supabase using Docker Compose, secure the server, configure automated backups, and monitor real-world resource usage. Once you have actual performance data, you can determine whether the server needs optimization, more resources, or a more advanced architecture.
For developers who want greater infrastructure control and are comfortable managing Linux, Docker, PostgreSQL, and AWS, a self-hosted Supabase deployment can be an effective foundation for production applications without being locked into increasingly expensive managed infrastructure tiers.
No spam. Unsubscribe anytime.