In our inaugural post of our How We Built series, we dive into how we engineered a scalable, real‑time backend infrastructure for a food-business client using Supabase, the open-source Backend-as-a-Service (BaaS) built on PostgreSQL.
Why Supabase Was Our Top Choice
With its fully managed PostgreSQL database, supplementary REST & GraphQL APIs, real-time subscriptions, integrated file storage, native authentication, and serverless capabilities, Supabase gives us Firebase-like speed with SQL-level flexibility. This mix was ideal for our mission-critical food-ordering platform—requiring real-time menu updates, user logins, media storage, and secure all-in-one architecture.
Bootstraping the Supabase Backend
We began in the Supabase dashboard:
- Created a new project.
- Defined tables:
users
,menus
,orders
,order_items
. - Enabled Row-Level Security (RLS) for secure and granular data access.
- Configured storage buckets for menu and dish images.
- Activated real-time sync on critical tables for live updates
Structuring for Clarity & Performance
We structured our tables as follows:
- users: Stores user metadata linked to Supabase’s auth system.
- menus: Catalog of dish entries with fields like dish name, price, and
image_url
referencing storage. - orders: Tracks
user_id
, status, timestamps. - order_items: Lists dishes included in each order with quantities and prices.
This relational model enabled normalized queries, strong referential integrity, and optimized live updates.
Auto-Generated APIs: Out‑of‑the‑Box CRUD
Supabase auto-generates REST endpoints via PostgREST and GraphQL via pg_graphql based on table schemas. With these tools, we could:
- Fetch menu items directly: jsCopyEdit
supabase.from('menus').select('*');
- Create and fetch orders.
- Manage user sessions—no custom endpoints needed.
Authentication & Security
User identity and access control were vital:
- We enabled email/password signup via Supabase Auth.
- Integrated
auth.uid()
into RLS policies—for example, orders visible only to their owners. - Enforced secure file access via bucket-level policies.
- Valid sessions ensured with JWTs—no manual token handling.
Real-Time Subscriptions: Live Updates Everywhere
Live ordering was key: kitchen UI had always-updated order feeds and customers could track status in real time:
supabase
.from('orders')
.on('INSERT', payload => updateKitchenUI(payload.new))
.subscribe();
Powered by Postgres’ LISTEN/NOTIFY
, this broadcast system scales efficiently and is more flexible than polling.
File Storage: Serving Media at Scale
Dish photos were stored with Supabase storage. Workflow:
- Upload image.
- Store resulting
publicURL
in themenus
table. - Display dish images on the frontend using that URL.
Supabase automatically handles CDN delivery and secure public/private access.
Serverless Edge Functions: Business Logic at the Edge
We implemented key actions via Edge Functions:
- Order confirmation emails.
- Webhooks to POS systems upon order placement.
- Business logic triggers outside API polling.
Supabase edge functions (powered by Deno) execute with low latency and minimal infra overhead.
Deployment & Best Practices
To ensure a successful rollout:
- We scoped real-time tables carefully to reduce unnecessary events.
- Employed TypeScript for API safety.
- Cleanly unsubscribed from real-time streams in the UI.
- Stored sensitive keys in environment variables.
These steps improved performance, retained strong security, and ensured maintainability.
What we learned:
- Supabase’s cohesive ecosystem dramatically speeds up backend development.
- Built-in real-time support and RLS enable fully secure interactive applications.
- Serverless functions streamline integrations and backend logic effortlessly.
Leave a Reply