Skip to content
BurnerByte

architecture

Architecture Overview

How BurnerByte's two-binary architecture works.

System Design

BurnerByte runs as two independent Go binaries that share the same database, Redis, and object storage:

  • cmd/api — HTTP API server (Chi router) + 7 background workers
  • cmd/smtpd — SMTP inbound server with worker pool

Both binaries load the same config.yaml and connect to the same PostgreSQL, Redis, and MinIO instances. They can be scaled independently.

Request Flow

API Request

text
Client → Security Headers → Body Size Limit → CORS → Rate Limiter → Auth Middleware → RBAC Check → Handler → Service → Repository → PostgreSQL

Middleware chain: RequestID → RealIP → Logger → Recoverer → SecurityHeaders → MaxBytesReader → CORS → (route-specific: Auth, RateLimit, RBAC).

Inbound Email

text
External MTA → SMTPD (port 2525) → Router (domain lookup) → Handler (MIME parse) → PostgreSQL + MinIO                                                                                  → WebSocket Hub                                                                                  → Webhook Dispatcher

The SMTP server accepts connections, validates the recipient domain against the database, parses MIME content with enmime, stores the email and attachments, then fans out to WebSocket and webhook subscribers. A Redis pub/sub bridge carries inbox events from SMTPD to the API server, which broadcasts them to the WebSocket hubs, persists the notification row, and increments the analytics counters.

Key Components

ComponentPackagePurpose
HTTP Routergo-chi/chiRESTful API routing
Authinternal/authJWT tokens, sessions, lockout, SSO
RBACinternal/auth/rbacRole-based access control
Handlersinternal/handler20 HTTP handler files
Servicesinternal/service13 business logic services
Repositoriesinternal/repository23 PostgreSQL + 1 Redis repo
SMTPinternal/smtpServer, router, handler, listener
Workersinternal/worker7 background jobs
Realtimeinternal/realtimeWebSocket hubs for inbox + notifications
Webhooksinternal/webhookHMAC-signed dispatch with retry
Mailerinternal/mailerOutbound email (invites, resets)
Storageinternal/storageS3/MinIO client with automatic local-filesystem fallback, hot-swappable via storage.Manager
Auditinternal/auditActivity recording
Configinternal/configViper-based config + DB overrides

Database

36 tables across 50 migrations (including SSO and analytics tables). Key tables: users, organizations, org_memberships, teams, team_memberships, domains, domain_assignments, inboxes, emails, attachments, webhooks, webhook_delivery_logs, api_keys, audit_logs, invites, sessions, setup_state, password_reset_tokens, system_configs, email_verification_tokens, roles, permissions, role_permissions, notifications.

74 indexes keep lookups fast, and 8 triggers maintain automatic updated_at timestamps (six tables), the full-text search_vector on emails, and the revocation of a departing user's API keys. Cascading deletes are enforced by foreign-key ON DELETE CASCADE constraints, not triggers.

Frontend

Next.js 16 with App Router, React 19, shadcn/ui components, Zustand for state, TanStack Query for server state, and Recharts for analytics visualization. 26 pages with consistent UX patterns (loading skeletons, error states, empty states, confirmation dialogs, optimistic updates).

A server-authoritative onboarding gate redirects users without an organization to /onboarding (system admins are exempt). Org-scoped pages show a NoOrgState empty state with a create-org CTA, and team-scoped pages show a NoTeamState with a create-team CTA, ensuring there are no dead-end screens regardless of the user's provisioning state.