How to Deploy Instant – Open-Source Firebase Alternative

Updated on 16 April, 2026
Deploy Instant as a self-hosted alternative to Firebase for real-time backend and database workflows.
How to Deploy Instant – Open-Source Firebase Alternative header image

Instant is an open-source, real-time backend platform for web applications. It provides a client-side database with built-in support for authentication, relational queries, transactions, file storage, and real-time data synchronization. Instant serves as a self-hosted alternative to Firebase and removes the need to manage custom backend APIs or WebSocket infrastructure.

This article explains how to deploy Instant on a Linux server using Docker Compose. It covers directory setup, environment configuration, Traefik reverse proxy integration for automatic HTTPS, and backend API verification using a sample database workflow.

Prerequisites

Before you begin, you need to:

Set Up the Directory Structure, Configuration, and Environment Variables

Instant runs as a containerized backend service built from the official source repository. The project directory stores the source code, Docker Compose configuration, and environment variables.

  1. Create a project directory for Instant and navigate into it.

    console
    $ mkdir ~/instant
    $ cd ~/instant
    
  2. Clone the official Instant repository. InstantDB does not publish pre-built Docker images or versioned releases, so the server is built from source using the official repository.

    console
    $ git clone https://github.com/instantdb/instant.git app
    

    The repository is cloned into a folder named app to keep the project path clean.

  3. Navigate to the server directory.

    console
    $ cd app/server
    
  4. Rename the default docker-compose.yml file to keep it as a backup.

    console
    $ mv docker-compose.yml docker-compose.yml.bak
    
  5. Create the environment configuration file.

    console
    $ nano .env
    

    Add the following configuration:

    ini
    TZ=UTC
    
    DOMAIN=instant.example.com
    EMAIL=admin@example.com
    
    POSTGRES_USER=instant
    POSTGRES_PASSWORD=YOUR_DATABASE_PASSWORD
    POSTGRES_DB=instant
    

    Replace the placeholders:

    • instant.example.com: Your registered domain name.
    • admin@example.com: Your email address for Let's Encrypt notifications.
    • YOUR_DATABASE_PASSWORD: A strong password for the PostgreSQL database.

    Save and close the file.

Deploy with Docker Compose

The deployment stack consists of three services: Traefik handles reverse proxy and automatic TLS certificate management via Let's Encrypt, PostgreSQL stores application data with logical replication enabled, and the Instant server runs the backend application.

  1. Create the Docker Compose configuration file.

    console
    $ nano docker-compose.yml
    

    Add the following configuration:

    yaml
    services:
      traefik:
        image: traefik:v3.6
        container_name: traefik
        command:
          - "--providers.docker=true"
          - "--providers.docker.exposedbydefault=false"
          - "--entrypoints.web.address=:80"
          - "--entrypoints.websecure.address=:443"
          - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
          - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
          - "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
          - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
          - "--certificatesresolvers.letsencrypt.acme.email=${EMAIL}"
          - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
        ports:
          - "80:80"
          - "443:443"
        volumes:
          - "/var/run/docker.sock:/var/run/docker.sock:ro"
          - "./letsencrypt:/letsencrypt"
        restart: unless-stopped
    
      postgres:
        image: ghcr.io/instantdb/postgresql:postgresql-16-pg-hint-plan
        container_name: postgres
        environment:
          POSTGRES_USER: ${POSTGRES_USER}
          POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
          POSTGRES_DB: ${POSTGRES_DB}
        volumes:
          - ./postgres-data:/var/lib/postgresql/data
        command:
          - postgres
          - -c
          - wal_level=logical
          - -c
          - max_replication_slots=4
          - -c
          - max_wal_senders=4
          - -c
          - shared_preload_libraries=pg_hint_plan
          - -c
          - random_page_cost=1.1
        healthcheck:
          test: ["CMD", "pg_isready", "-U", "instant"]
          interval: 10s
          timeout: 5s
          retries: 5
        restart: unless-stopped
    
      server:
        build:
          context: .
          dockerfile: Dockerfile-dev
        container_name: instant
        working_dir: /app
        command: ["make", "dev-oss"]
        depends_on:
          postgres:
            condition: service_healthy
        environment:
          TZ: ${TZ}
          DATABASE_URL: "postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}"
          NREPL_BIND_ADDRESS: "0.0.0.0"
        volumes:
          - ./:/app
        expose:
          - "8888"
        labels:
          - "traefik.enable=true"
          - "traefik.http.routers.instant.rule=Host(`${DOMAIN}`)"
          - "traefik.http.routers.instant.entrypoints=websecure"
          - "traefik.http.routers.instant.tls.certresolver=letsencrypt"
          - "traefik.http.services.instant.loadbalancer.server.port=8888"
        restart: unless-stopped
    

    Save and close the file.

    In the above manifest:

    • services: Launches three containers managed by Docker Compose:
      • traefik: Functions as the reverse proxy and TLS termination point.
      • postgres: Runs the Instant-specific PostgreSQL image with required extensions.
      • server: Builds and runs the Instant backend application.
    • image: Defines which container image each service uses. The PostgreSQL image is maintained by InstantDB and includes the pg_hint_plan extension required for query optimization.
    • container_name: Assigns predictable names to containers, simplifying log inspection and management commands.
    • command (Traefik): Establishes Traefik's operational parameters: Docker provider integration, HTTP and HTTPS entry points, automatic redirection from HTTP to HTTPS, and Let's Encrypt certificate acquisition.
    • command (PostgreSQL): Enables logical replication and performance tuning parameters required by Instant for real-time data synchronization.
    • build (server): Builds the Instant backend image from the Dockerfile in the repository.
    • depends_on: Ensures the server starts only after PostgreSQL reports a healthy state.
    • expose (server): Makes port 8888 available internally for Traefik routing without exposing it directly to the host network.
    • volumes:
      • The ./postgres-data bind mount stores database files on the host persistently.
      • The ./letsencrypt bind mount retains TLS certificates between container restarts.
      • The Docker socket mount (/var/run/docker.sock) enables Traefik to detect and configure routes for running containers automatically.
    • labels (server): Instructs Traefik to route HTTPS traffic for the configured domain to the Instant backend on port 8888.
    • healthcheck: Verifies PostgreSQL readiness before the backend starts.
    • restart: unless-stopped: Configures containers to restart automatically after crashes or server reboots, unless explicitly stopped.
  2. Start the containers in detached mode.

    console
    $ docker compose up -d --build
    

    The --build flag builds the Instant server image from source on first run.

  3. Verify that all containers are running.

    console
    $ docker compose ps
    

    The output displays three running containers with Traefik listening on ports 80 and 443, PostgreSQL reporting a healthy status, and the Instant server exposing port 8888.

  4. View the logs for the services.

    console
    $ docker compose logs
    

    The output shows PostgreSQL initialization messages, the Instant server startup sequence, and Traefik registering routes for the configured domain.

    For more information on managing a Docker Compose stack, see the How to Use Docker Compose article.

Access and Configure Instant

The Instant backend exposes a REST API for application management and real-time data operations. Traefik routes HTTPS traffic to the backend and automatically provisions TLS certificates from Let's Encrypt.

  1. Verify that the Instant backend is accessible. Replace instant.example.com with your configured domain name.

    console
    $ curl https://instant.example.com
    

    Output:

    <code>Welcome to Instant's Backend!</code>
    Note
    The backend completes initialization after the containers start. If the curl command returns a connection error, wait a few moments for initialization to complete and run the command again. Let's Encrypt certificate provisioning may also take up to a minute on first access.
  2. Open your web browser and navigate to https://instant.example.com, replacing instant.example.com with your configured domain name.

    The page displays the welcome message, confirming HTTPS routing through Traefik is working correctly.

Verify Database Connectivity

Instant uses PostgreSQL as its persistent store for application data. The following steps confirm database connectivity and query functionality by creating a test table, inserting sample data, and querying it from the PostgreSQL container.

  1. Connect to the PostgreSQL container.

    console
    $ docker compose exec postgres psql -U instant -d instant
    

    The prompt changes to instant=# on successful connection.

  2. Create a sample table.

    psql
    instant=# CREATE TABLE messages (id SERIAL PRIMARY KEY, content TEXT NOT NULL, created_at TIMESTAMP DEFAULT NOW());
    
  3. Insert test records into the table.

    psql
    instant=# INSERT INTO messages (content) VALUES ('Hello from Instant'), ('Real-time sync test');
    

    Output:

    INSERT 0 2
  4. Query the stored data.

    psql
    instant=# SELECT id, content, created_at FROM messages ORDER BY created_at DESC;
    

    The output displays both inserted rows with their auto-generated IDs and timestamps reflecting the current time.

  5. Exit the database shell.

    psql
    instant=# \q
    
  6. Review the backend logs to confirm that the server is running without errors.

    console
    $ docker compose logs --tail=20 server
    

    The logs display initialization messages and confirm the server is accepting connections.

Conclusion

You have successfully deployed Instant on your Linux server using Docker Compose with PostgreSQL as the backend database and Traefik for automatic HTTPS. The setup provides a self-hosted real-time backend platform with persistent storage, authentication support, and relational query capabilities. Instant eliminates the need for custom backend APIs and WebSocket infrastructure while providing Firebase-like functionality. For advanced configuration, client SDK integration, and API reference, refer to the official Instant documentation.

Comments