/Resources
/Backend
/How to Contribute
/Billing Service Setup

Billing Service Setup

Learn how to set up, configure, and run the Reloop billing service locally.

The Billing Service is an ElysiaJS microservice that handles user subscription tiers, credits tracking, billing transaction history, and Stripe portal integration. It acts as the platform's gatekeeper, enforcing sending limits and managing invoice history.

Prerequisite First

Before configuring the Billing Service, ensure you have completed the base Local Development Setup (installed Bun, configured the hosts file, and started the Docker container stack).


Quick Start

You can boot the Billing Service development server instantly using workspace scripts from the root directory:

# Start the dev server with hot reloading
bun be:billing:dev
cd apps/backend/billing
bun dev

Once running, the Billing API will listen locally on port 8023. You can query it via Caddy at https://local.reloop.sh/api/billing 🎉


Service Information

  • Directory Location: apps/backend/billing/
  • Local Listening Port: 8023 (ElysiaJS gateway)
  • Unified Access Route: https://local.reloop.sh/api/billing
  • Primary Tech Stack: ElysiaJS, PostgreSQL, Redis, NATS
  • Dependencies: Relies on PostgreSQL (to record transactions/invoices) and NATS (to receive subscription & usage update triggers).

Environment Configuration

The Billing Service environment variables are defined in apps/backend/billing/.env. Running bun env:setup at the root populates this file with defaults:

# Server Port Configuration
BILLING_PORT=8023
NODE_ENV=development

# Core Platform Settings
INITIAL_CREDITS=100

# Event Bus Broker
NATS_URL=nats://localhost:4222

Reference Table

VariableRequiredDefault ValueDescription
BILLING_PORTYES8023Port number the Elysia app listens to on the host.
INITIAL_CREDITSYES100Free email credits allocated to a newly created organization.
NATS_URLYESnats://localhost:4222Connection URL for NATS event bus messaging.
NODE_ENVYESdevelopmentActive environment scope (development or production).

(Note: Shared database connections inherit PG_URL globally through root workspace parameters.)


Development Commands

Execute billing service operations from the monorepo root directory using Turborepo filters:

CommandActionScope
bun be:billing:devStart the Billing dev server with hot reloadingDevelopment
bun run --filter=billing buildCompile the Billing service for productionProduction
bun run --filter=billing startRun the compiled production build locallyProduction
bun run --filter=billing check-typesVerify TypeScript type-safetyCode Quality

Database Schema & Relationships

The relational subscription packages, invoice schedules, credit balance ledgers, and usage tracking schemas are defined inside packages/db/src/schema/billing.ts.

Enums

EnumValuesDescription
billing_cyclemonthly · annualCharging occurrence frequency
subscription_statusactive · past_due · cancelled · trialing · pausedWorkspace subscription lifecycle state
ledger_entry_typecredit_purchased · email_sent · rollover_applied · manual_adjustment · refund · plan_change · period_resetTransaction types in the credit ledger
email_send_statusqueued · sent · skipped · failed · bouncedOverage/credit tracking delivery state
skip_reasonover_limit · unsubscribed · duplicate · invalid_address · suppressed · dry_runLogical skips avoiding billing drops
invoice_statusdraft · open · paid · void · uncollectibleInvoice collection states

plan Table

Defines base tiers, credits entitlements, and limits for the platform.

ColumnTypeDefaultDescription
idtextpln_{cuid}Primary Key
namevarchar(100)Tier display name (e.g. Startup)
monthlyCreditsintegerTotal default monthly volume capacity
overageLimitinteger0Absolute ceiling allowed past base capacity
basePriceUsddecimalBase charge rate for the package
overagePricePerEmaildecimal0Unit charge per overage dispatch
billingCyclebilling_cyclemonthlyPlan billing recurring frequency
rolloverEnabledbooleanfalseCarries unused volume to next periods
maxRolloverCreditsintegernullCap limit for rollovers
ratePerSecondinteger50Concurrent throughput limit
maxAttachmentSizeMbinteger10Size capacity for outbound uploads
isActivebooleantrueSystem offering visibility flag

subscription Table

Links a workspace/organization to a chosen subscription tier with active usage counters.

ColumnTypeDefaultDescription
idtextsub_{cuid}Primary Key
organizationIdtextForeign Key → organization.id
planIdtextForeign Key → plan.id
statussubscription_statusactiveActive subscription state
creditsUsedinteger0Base package credits spent
creditsRemaininginteger0Unspent base credits remaining
rolloverCreditsinteger0Accumulated unspent credits carried over
overageCreditsUsedinteger0Total overage consumed in period
currentPeriodStarttimestampCurrent billing window lower bound
currentPeriodEndtimestampCurrent billing window upper bound
externalSubscriptionIdvarcharnullAssociated Stripe subscription ID

credit_ledger Table

Audit ledger tracking every transactional shift in a workspace's credit balance.

ColumnTypeDefaultDescription
idtextcld_{cuid}Primary Key
organizationIdtextForeign Key → organization.id
subscriptionIdtextForeign Key → subscription.id
entryTypeledger_entry_typeType of transaction performed
deltaintegerChange magnitude (+/- credits shift)
balanceAfterintegerUpdated ledger total after change
reasontextnullNarrative descriptive context
referenceIdtextnullExternal reference (e.g. email_send.id)

Other Billing Tables

  • billing_invoice: Captures invoice statements, credits included/used, overage totals, and payment confirmation statuses.
  • email_send: High-performance operational log mapping outbound messages to specific subscription balances for overage verification and credit deductions.

Interactive API Docs (Swagger)

The Billing Service exposes dynamic OpenAPI specs. To run test queries and explore billing endpoints:

  1. Open your browser and navigate to the interactive Swagger playground at https://local.reloop.sh/api/billing/openapi (or http://localhost:8023/api/billing/openapi directly).
  2. Use the interactive Swagger UI playground to inspect schemas and execute test queries.

Core Features Explained

  • Credit Tracking & Balances: Deducts outbound email credits in real time, communicating with mailing queues to block campaigns if a workspace's balance reaches 0.
  • NATS Pub-Sub Integration: Subscribes to events like billing.quota-warning to trigger system emails when a workspace consumes 80% or 100% of its credit allocation.
  • Stripe Subscriptions: Interfaces with Stripe billing portals, handling webhook listeners for webhook payments, subscription renewals, cancellations, and invoicing records.
  • Relational Billing Schemas: Stores ledger data, monthly credits usage metrics, Stripe metadata, and transaction states inside the PostgreSQL billing_invoice and billing_transaction tables.