Skip to content
Return to Projects
Case Study

Payday Chat

A real-time, members-only network for online business founders.

The Problem

Founders needed a private, high-signal place to network, build teams, and scale revenue — not another noisy public feed. Payday Chat is invite-only and built around real-time collaboration.

My Role

Built solo with AI-assisted development — Flutter client, NestJS API, data model, real-time layer, and deployment.

Highlights

  • Real-time messaging with presence and live events over WebSockets
  • One NestJS API powering both a Flutter mobile app and a web client
  • PostgreSQL domain model with Redis for caching and pub/sub fan-out
  • NGINX gateway, Stripe payments, and OAuth authentication

Stack

FlutterDartNestJSPostgreSQLRedisNGINXStripe

Constraints

  • Invite-only product — auth and access control had to be correct from day one.
  • One backend, two clients (Flutter + web) — schema and contracts had to be shared, not duplicated.
  • Realtime is a feature, not a nice-to-have — presence and live events must survive reconnects.

System Architecture

Clients
Flutter Mobile App
Web App
Gateway
NGINX
API
NestJS REST
WebSocket Gateway
Data
PostgreSQL
Redis (cache + pub/sub)
External
Stripe
OAuth

Key Trade-offs

The decisions worth defending — what I chose, what I turned down, and why.

Realtime transport

Chose

WebSockets with Redis pub/sub fan-out

Rejected

Long-polling or third-party realtime SaaS

Predictable latency, no per-message vendor cost, and Redis already in the stack for caching — one fewer moving part.

Mobile client framework

Chose

Flutter (single codebase for iOS + Android)

Rejected

Native Swift + Kotlin clients

Solo build — two native clients would have doubled the surface area and slowed iteration on the API.

API style

Chose

REST + dedicated WebSocket gateway

Rejected

GraphQL subscriptions

Simpler operational story, easier to cache at the NGINX layer, and the realtime channel stays an explicit, observable component.

What I'd Do Differently

An honest retrospective — the stuff I'd change with more time, more users, or a second pass.

  1. 1Introduce contract tests between the NestJS API and the Flutter client earlier — a few breakages were caught only at runtime.
  2. 2Move long-lived sockets to a dedicated process so API deploys don't drop client connections.
  3. 3Add structured event versioning from day one instead of retrofitting it once the schema started moving.

Technical Deep-Dive

Architecture, specifications, and implementation details.

Payday — Developer Documentation

"

How to use with VS Code Copilot: Place the entire payday-docs/ folder at the root of your repo. Copilot reads .github/copilot-instructions.md automatically as global context. Open any numbered doc before working on that feature — Copilot will use it as active context.


#File Index

FileDescription
.github/copilot-instructions.mdMaster Copilot context — read first, always active
00_README.mdThis file — index and quick start
01_SPEC_Master.mdComplete product + system specification
02_API_Contracts.mdEvery endpoint — method, body, response, errors
03_Domain_Events.mdAll NestJS modules, services, BullMQ queues
04_PostgreSQL_Schema.sqlFull database schema — extensions, enums, tables, indexes, triggers
05_Indexes_and_Performance.sqlIndex reference, query patterns, performance targets
06_Data_Retention_and_Redis.mdRedis DB layout, cache keys, TTLs, data retention rules
07_Auth_and_OAuth.mdJWT lifecycle, Google OAuth, Apple Sign-In full spec
08_Gateway_and_Realtime.mdSocket.io architecture, room names, all events, presence system
09_AI_Match_Engine.mdpgvector embeddings, match algorithm, BullMQ jobs
10_Live_Event_Streaming.mdRTMP self-hosted streaming, HLS playback, Socket.io events
11_Payments_and_Stripe.mdStripe subscriptions, webhook handler, tier mapping
12_Notifications_Module.mdMulti-channel dispatch, email templates, preferences
13_Docker_Architecture.mdAll containers, volumes, networks, docker-compose spec
14_Environment_Variables.mdEvery env var with type, default, and description
15_Infrastructure_and_Deployment.mdServer sizing, SSL, firewall, backup, scaling
16_NestJS_Patterns.mdCanonical module, entity, DTO, service, controller boilerplate
17_Naming_Conventions.mdFiles, classes, DB columns, Redis keys, Socket rooms
18_Docker_Setup_Checklist.mdStep-by-step local Docker startup guide
19_Security_Checklist.mdFull security hardening checklist
20_Pre_Launch_Checklist.mdEverything to verify before going live
21_New_Module_Checklist.mdSteps to add a new NestJS feature module
22_Compliance_and_Legal.mdGDPR, CCPA, COPPA, PCI-DSS, App Store, email compliance
23_Production_Readiness_Checklist.mdMaster go-live checklist — every feature, every system
ci/db-backup.shAutomated PostgreSQL backup script
ci/db-restore-validate.shRestore + validate backup integrity
ci/healthcheck.shFull stack health check script
ci/release-gate.shPre-deploy checks — blocks release if any check fails
ci/release-gate-policy.mdPolicy document for release gate rules

#Quick Start

# 1. Enter backend folder
cd payday-backend

# 2. Set up environment
cp .env.example .env
# Fill in: DB_PASSWORD, REDIS_PASSWORD, JWT_ACCESS_SECRET, JWT_REFRESH_SECRET, COOKIE_SECRET

# 3. Start everything
docker compose up -d

# 4. Verify
curl http://localhost/health

# 5. Open tools
#   Swagger:   http://localhost/docs
#   Mailhog:   http://localhost:8025
#   Portainer: http://localhost:9000

#Key Ports

URLService
http://localhost/api/v1/REST API (via Nginx)
http://localhost/docsSwagger docs
http://localhost:8025Mailhog (email testing)
http://localhost:9000Portainer (Docker UI)
localhost:5432PostgreSQL
localhost:6379Redis
~ End of Document ~