Supabase in Your App
Reading, writing and listening for changes in code, and Supabase vs Railway PostgreSQL

Pixl presents
Reading, writing and live updates in code, then Supabase versus plain Railway PostgreSQL. Spoiler, the answer is it depends.Reading, writing and live updates in code, then Supabase versus plain Railway PostgreSQL. Spoiler, the answer is it depends.

Using Supabase in Your Code#
Here's a simple example. Don't stress about memorizing any of it. Just notice how straightforward it reads.
Setting Up the Client#
Every example below imports a supabase client from a file called supabaseClient.js, so make that first. Install Supabase's JavaScript library in your project folder.
npm install @supabase/supabase-jsGrab your project URL and publishable key from the Connect panel in the Supabase dashboard and put them in .env.local. These are the Next.js names, and other frameworks use their own prefix.
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=sb_publishable_...Then create the client once and export it.
// supabaseClient.js
import { createClient } from '@supabase/supabase-js'
export const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL,
process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY
)The publishable key is safe to use in the browser. What keeps your data safe is row level security (RLS), which is a set of rules on each table that says who can read and write which rows.
Reading Data#
import { supabase } from './supabaseClient'
// Get all users
const { data: users } = await supabase
.from('users')
.select('*')
// Get one user
const { data: user } = await supabase
.from('users')
.select('*')
.eq('id', 1)
.single()Writing Data#
// Add a new user (and get the new row back)
const { data, error } = await supabase
.from('users')
.insert({
name: 'Alex',
email: '[email protected]'
})
.select()That .select() on the end matters. Without it, Supabase saves the row but hands you back nothing, and you'll be staring at a null wondering what broke.
Listening for Real-time Changes#
// Listen for new messages
supabase
.channel('messages')
.on('postgres_changes',
{ event: 'INSERT', schema: 'public', table: 'messages' },
(payload) => {
console.log('New message:', payload.new)
}
)
.subscribe()Any time a message gets added to the database, your code hears about it instantly.
One setup step first though. Real-time is off for each table until you switch it on. In the Supabase dashboard, find the supabase_realtime publication and toggle on the tables you want to listen to (the messages table here). Your row level security rules also decide which changes each user actually gets.
Supabase vs. Railway PostgreSQL#

You might be thinking "wait, didn't we already learn about Railway for databases?" Good catch!
Supabase and Railway can BOTH host PostgreSQL databases. Here's when each one makes sense.
Use Supabase When:#
- You want real-time updates
- You want a simple API without writing backend code
- You're building something fast
- You like having a visual dashboard to look at your data
- You want built-in extras (auth, storage, edge functions)
Use Railway PostgreSQL When:#
- You just need a plain database
- You're using an ORM like Prisma (which we covered earlier)
- You want more control over your database
- You're already deploying other stuff on Railway
This lesson ends with 2 short activities.
