Architecture Overview

Flow runs on a Supabase-only backend: a single stack of PostgreSQL (with RLS), Edge Functions (Deno/TypeScript), Realtime, and Storage. No microservices, no multiple databases, no message queues — all business logic lives either in the database or in Edge Functions called via HTTP.

Architectural decision — 2026-03-29

Flow migrated from Node.js microservices + MongoDB + Redis + Elasticsearch to Supabase-only. Motivation: eliminate dual-database inconsistency, cut operational costs to near zero, simplify deployment. Legacy microservice code still exists in backend/ but is not used or touched — it will be archived in a legacy/microservices branch once fully decoupled.

Full design spec: Supabase-only Migration Design

Tech Stack

LayerTechnology
MobileFlutter · Dart · Riverpod · GoRouter · Supabase Flutter SDK
WebNext.js 16 · React 19 · TypeScript · Tailwind CSS 4 · TanStack Query
APISupabase PostgREST (auto-generated from Postgres schema) + custom Edge Functions
DatabasePostgreSQL with Row Level Security on every table
GeospatialPostGIS (geo_point column)
Searchpg_trgm for native fuzzy matching in Postgres
RealtimeSupabase Realtime (Postgres changes subscriptions + broadcast)
AuthSupabase Auth (email/password, JWT auto-refresh)
PushFirebase Cloud Messaging, triggered from Edge Functions
EmailResend API for critical notifications
AI/MLCustom Edge Functions (recommendations, matchmaking, moderation)

Core Components

Database

Postgres with ~30 main tables (profiles, events, venues, chats, connections, crews, badges, notifications, recommendations_cache, etc.). RLS on every table: no API layer needs to re-verify authorization — the database rejects unauthorized queries directly based on auth.uid().

Details: Database Schema

Edge Functions

Seven Edge Functions in Deno/TypeScript handle logic that cannot live purely in SQL: push/email notifications, recommendation scoring, matchmaking, content moderation, XP/badge assignment.

FunctionTriggerPurpose
send-notificationINSERT on notificationsFCM push + Resend email
process-rsvpChange on event_attendeesXP, cache invalidation, badge
compute-recommendationsCron (6h) / on-demandEvent scoring
compute-matchmakingOn-demandPeople scoring
moderate-contentINSERT on messages/commentsKeyword filter + flag
compute-connection-depthINSERT on event_attendeesFriendship tier
evaluate-badgesCalled from process-rsvpBadge criteria check

Details: API Reference

Clients

  • Admin Portal (web/): multi-role dashboard (admin, vendor, moderator) in Next.js 16. Server Components for SSR, TanStack Query for mutations.
  • Mobile App (flow_mobile/): Flutter iOS + Android. Riverpod for state management, GoRouter for navigation, Supabase Flutter SDK for data layer.

Both clients talk directly to Supabase — no intermediate API gateway, no custom serialization, TypeScript/Dart types auto-generated from the schema.

What Does NOT Exist (by design)

  • ❌ No custom API gateway (Express, Fastify, etc.)
  • ❌ No message broker (RabbitMQ, Kafka, etc.)
  • ❌ No secondary database (MongoDB, DynamoDB, etc.)
  • ❌ No custom cache layer (Redis, Memcached) — Postgres suffices, with materialized views where performance is needed
  • ❌ No separate search engine — pg_trgm handles fuzzy matching for current use cases

These choices are reversible — but any new technology addition must be justified by a real measured problem, not anticipated.