The self-hosted, headless waitlist API. Define custom schemas in seconds, own your data, and deploy anywhere.
Lobby is an open-source, developer-first, self-hosted waitlist backend. Traditional waitlist SaaS platforms lock your data behind their subscription models, enforce rigid fields, and limit customizations. Lobby solves this by giving you:
- Complete Data Ownership: Your signups live entirely in your own PostgreSQL database.
- 100% Headless & Customizable: Define your waitlist's name and schema with an interactive wizard, plug it into your custom frontend, and walk away.
- Instant Deployments: Go from a blank terminal to a fully functional, production-ready waitlist API in less than 5 minutes.
- Zero Data Loss Migrations: Safely add, modify, or remove signup fields post-launch using automatically generated SQL migrations.
Lobby is engineered with high-performance, industry-standard modern web technologies:
- Framework: NestJS 11 β reliable, scalable, and highly structured.
- Database Interface: Kysely β ultra-fast, SQL-injection safe, and fully type-safe dynamic SQL compiler.
- Data Layer: PostgreSQL β robust relational database.
- Queuing & Workers: BullMQ & Redis β transactional mail queuing for heavy signup loads.
- Communications: Resend β modern developer-friendly transactional email service.
- CLI Wizard: Clack (
@clack/prompts) β beautiful, interactive console prompts.
sequenceDiagram
autonumber
actor Developer
actor User as Signup Client
participant CLI as Lobby CLI Setup
participant API as Lobby NestJS API
participant DB as PostgreSQL
participant Redis as BullMQ Redis
participant Resend as Resend SDK
Note over Developer, DB: 1. Setup Phase
Developer->>CLI: pnpm run setup
CLI->>Developer: Prompts (Waitlist name, fields, email configs)
CLI->>Developer: Generates lobby.config.json & SQL migration file
Developer->>DB: pnpm run migration:run (Applies schema transactions)
Note over User, Resend: 2. Runtime Phase
User->>API: POST /api/v1/waitlist/join (dynamic data payload)
API->>API: Validates data types against lobby.config.json at runtime
API->>DB: Check for duplicate emails & atomic position assignment (via DB sequence)
DB-->>API: Returns assigned waitlist position
API->>Redis: Enqueues SEND_CONFIRMATION_EMAIL job (if enabled)
API-->>User: Returns 201 Created (ID, position, success message)
Note over Redis, Resend: 3. Background Mail Worker
Redis->>API: BullMQ Processor pulls active mail job
API->>Resend: Dispatches custom email variables
Deploying your waitlist backend is straightforward. Ensure you have Node.js (>=22.0.0) and pnpm (>=10.33.4) installed. (Note: A PostgreSQL database instance is only required starting at Step 4).
git clone https://github.com/josephsystems/lobby.git && cd lobby && pnpm installpnpm run setupThis command generates:
lobby.config.jsonβ the source of truth for your waitlist schema.migrations/{timestamp}_initial_setup.sqlβ a custom SQL migration mapping your fields directly into PostgreSQL.
Copy the template .env.example to .env and configure your credentials:
cp .env.example .envNote
Resend Template Variables: Your Resend template will receive the following variables dynamically:
email: The signup's email address.position: The signup's queue position (integer).- Any custom fields configured in
lobby.config.json(e.g.,first_name,last_name, etc.).
Apply the migration files to construct your custom database tables:
pnpm run migration:runStart the NestJS development server:
pnpm run start:devYour waitlist API is now active at http://localhost:3000/api/v1! π
Submits a signup request. Dynamic fields are added to fields and validated against the schema defined in lobby.config.json.
- Route:
POST /api/v1/waitlist/join - Content-Type:
application/json
{
"email": "developer@example.com",
"fields": {
"first_name": "Ada",
"last_name": "Lovelace",
"phone": "+2348000000000"
}
}{
"status": "success",
"data": {
"id": "2e6b223c-f4e1-456b-be39-2a912bb0e7b8",
"email": "developer@example.com",
"position": 42,
"message": "You're on the list!",
"isNew": true
}
}Submitting the same email again is safe and returns the user's existing queue position:
{
"status": "success",
"data": {
"id": "2e6b223c-f4e1-456b-be39-2a912bb0e7b8",
"email": "developer@example.com",
"position": 42,
"message": "You're already on the list!",
"isNew": false
}
}Retrieves a user's current place in the waitlist queue.
- Route:
GET /api/v1/waitlist/position - Query Parameters:
email(string, required)
GET /api/v1/waitlist/position?email=developer@example.com{
"status": "success",
"data": {
"message": "Successfully retrieved position.",
"email": "developer@example.com",
"position": 42
}
}One of Lobby's core strengths is its ability to adapt. As your product evolves, you can safely add, modify, or remove fields with zero data loss. Lobby handles this using interactive CLI wizards that automatically update your configurations and generate standard SQL migration files.
Lobby provides three distinct commands to manage your database schema:
| Command | Description |
|---|---|
pnpm run fields |
Master Schema Wizard: Run this to edit existing fields first, followed by adding new ones. |
pnpm run fields:add |
Add Fields Wizard: Instantly prompt and append new custom columns to your schema. |
pnpm run fields:edit |
Edit Fields Wizard: Modify existing field attributes (rename, type, nullability) or safely drop columns. |
When you want to capture more information from your users, run the add fields wizard:
pnpm run fields:addHow it works:
- Interactive Prompt: The CLI guides you through defining the new field's name (validated to enforce
snake_case), data type (string,integer,boolean, etc.), nullability (required vs optional), and default values. - Config Update: It automatically appends the field definition to your local
lobby.config.json. - Migration Generation: Lobby outputs a custom SQL migration file in
migrations/{timestamp}_add_fields.sqldescribing the exactALTER TABLE waitlist_entries ADD COLUMN ...instructions. - Application: Apply the changes to your PostgreSQL instance by running:
pnpm run migration:run
To update or clean up existing custom fields, run the edit wizard:
pnpm run fields:editHow it works:
- Select Field: Choose a field to modify from the interactive CLI list.
- Choose Action:
- Rename: Safely renames the field.
- Change type: E.g., change from
integertostring. - Change required: Make a column required (
NOT NULL) or optional. - Change max length: Adjust string constraint lengths.
- Delete this field: Drops the column entirely.
- Migration Generation: Generates
migrations/{timestamp}_edit_fields.sqlcontaining the compiled DDL statements. - Application: Apply the changes to your database:
pnpm run migration:run
Warning
Avoid Direct Config Edits: Always use the CLI commands to manage your waitlist schema. Do not modify lobby.config.json directly. Editing the JSON file manually bypasses the migration generation process, causing your application's validation layers to fall out of sync with the underlying PostgreSQL database schema.
Caution
Destructive Operations & Production Data: Dropping columns or changing column types can result in permanent data loss or migration execution failures if existing data violates new constraints. Always backup your database and inspect the generated SQL migration files prior to executing them on production servers.
Lobby is a public-facing API but contains rigorous protection to prevent malicious third parties from spamming your backend from random origins:
- Origin Restriction: Lobby dynamically compiles regular expressions from the
APP_DOMAINenv variable. - CORS Behavior:
- Production (
NODE_ENV=production): Strictly allows requests only fromhttps://yourproduct.comand its HTTPS subdomains. - Staging: Allows standard localhost routes plus your secure production domains.
- Development: Automatically permits localhost ports (
http://localhost:*).
- Production (
To deploy Lobby, you will need a PostgreSQL Database and (optionally) a Redis Instance (required only if email is enabled in lobby.config.json) for BullMQ queues and rate limiting.
Choose one of the following providers:
- Supabase (Free/Managed): Create a project at Supabase. Copy the PostgreSQL transaction/session connection string from Database Settings.
- Neon (Free/Managed): Create a serverless database at Neon, which is excellent for serverless environments.
- Self-Hosted / VPS: Run PostgreSQL natively or via Docker.
Required only if email is enabled in lobby.config.json.
- Upstash (Free/Managed): Serverless Redis with a generous free tier. Create one at Upstash.
- Aiven (Free/Managed): Managed Redis with a free tier. Create one at Aiven.
- Redis (Free/Managed): Managed Redis with a free tier. Create one at Redis.
- Self-Hosted / VPS: Run Redis natively or via Docker.
Railway is a fast way to host your app, PostgreSQL, and Redis in one dashboard.
- Create a new project in Railway.
- Connect the GitHub repository.
- Add PostgreSQL and Redis (if using emails or want Throttle to use redis) database services to your project.
- Link your database and Redis connection details to Lobby's environment variables.
- Deploy! Railway will automatically detect Node.js, run your build script, and expose the application port.
Render is a developer-friendly platform for web services and databases.
- Create a PostgreSQL and Redis (if using emails or want Throttle to use redis) database on Render.
- Create a new Web Service on Render and connect your GitHub repository.
- Set the build and start commands:
- Build Command:
pnpm run build - Start Command:
pnpm run start:prod
- Build Command:
- Configure your environment variables in the Render dashboard.
- Deploy!
Lobby can be deployed as serverless functions on Vercel.
- Connect the repository to Vercel.
- Set up the required environment variables.
- Deploy!
[!NOTE] Ensure you use serverless-compatible database and Redis connections (like Neon and Upstash) that handle connection pooling efficiently.
Perfect if you want full ownership on your own server (DigitalOcean, Hetzner, AWS, etc.).
Lobby includes a docker-compose.yml that configures the API, PostgreSQL, and Redis automatically. To start:
docker-compose up -d --buildLobby will spin up, automatically run pending migrations, and listen on port 3000.
When deploying, ensure the following variables are configured on your host:
| Variable | Description | Required? |
|---|---|---|
DATABASE_URL |
PostgreSQL connection string | Yes |
APP_DOMAIN |
Frontend application domain (for CORS security, e.g., myapp.com) |
Yes |
NODE_ENV |
Environment mode (production, staging, or development) |
No (defaults to development) |
REDIS_HOST / REDIS_PORT |
Connection details for Redis | Yes if email is enabled in lobby.config.json |
REDIS_PASSWORD / REDIS_USER |
Auth details for Redis | No |
RESEND_API_KEY |
Resend API key for sending emails | Yes if email is enabled in lobby.config.json |
RESEND_CONFIRMATION_TEMPLATE_ID |
Resend template ID for waitlist verification | Yes if email is enabled in lobby.config.json |
DATABASE_SSL |
Enable TLS/SSL connection to PostgreSQL (true/false) |
No (defaults to false) |
DATABASE_CA_CERT_PATH |
Path to CA cert file for SSL verification | Yes if DATABASE_SSL=true |
Lobby's architecture is fully structured, leaving room for expansion in upcoming minor and major releases:
- v1.0.0 (Current): Core dynamic API, setup/schema CLI wizards, BullMQ email dispatchers, dynamic CORS, migration runner.
- v1.1.0: Referral tracking system (generate unique invite links and track signup invite counts).
- v2.0.0: Secure Admin Dashboard endpoints (
/admin/entries) with CSV exports, protected via custom API key middleware.
We welcome contributions of all kinds! Whether you are fixing a bug, adding a feature, or improving documentation, please read our Contributing Guide to get started.
Please also review our Code of Conduct to understand the expectations for participating in this project.
Lobby is open-source software licensed under the MIT License.