Row Level Security
Row Level Security (RLS) is a Postgres feature that filters rows based on the current user. When you query a table with RLS, the database itself decides what you can see — not your application code.
MassiCloud enables RLS by default on every table created through the platform. This is intentional: it’s safer to opt out of security than to opt in.
How it works
When a request hits the REST API with a JWT, MassiCloud:
- Validates the JWT
- Extracts claims:
sub(user id),role, etc. - Opens a Postgres connection
- Runs
SET LOCAL request.jwt.claims TO '<claims>' - Runs
SET LOCAL role TO 'authenticated'(or'anon'/'service_role') - Executes your query
RLS policies on the table can now read these via helper functions:
auth.uid()— the user’s UUIDauth.role()—'authenticated'or'anon'auth.email()— the user’s email
Default policies
When you create a table through the portal, MassiCloud adds two default policies:
- Users see own rows — if the table has a
user_idcolumn, only the user whose ID matches can read or modify. - Service role full access —
service_rolerequests bypass RLS entirely.
If your table doesn’t have a user_id column, the first policy is replaced with “Authenticated read all” — any logged-in user can read all rows, but nobody but service_role can modify.
You can modify these from the portal’s Schema tab → Policies panel.
Writing your own policies
Common patterns:
Users can manage their own rows:
CREATE POLICY "users manage own" ON todos FOR ALL TO authenticated USING (user_id = auth.uid()) WITH CHECK (user_id = auth.uid())Anyone can read; only authenticated users can create:
CREATE POLICY "public read" ON posts FOR SELECT TO anon, authenticated USING (true);
CREATE POLICY "auth insert" ON posts FOR INSERT TO authenticated WITH CHECK (auth.uid() IS NOT NULL);Only the row’s author can update:
CREATE POLICY "author updates" ON posts FOR UPDATE TO authenticated USING (author_id = auth.uid());Important edge cases
- A table with RLS enabled but no policies blocks everything, except
service_rolewhich bypasses RLS. If your query returns[]when it shouldn’t, check that policies exist. - INSERT uses
WITH CHECK, notUSING. Make sure your INSERT policies defineWITH CHECK. - UPDATE uses both:
USINGfor which rows can be matched,WITH CHECKfor what the new row is allowed to look like.