Thuta Learning
IntermediateDevOps & Toolsintermediate

Supabase

What you'll walk away with

  • Explain the core ideas behind Supabase
  • Read the diagram/table and identify how these platform categories differ
  • Explain how you would choose the right platform category for a real project

Build the mental model

Supabase's shape: a standard Postgres database at the core, with Supabase generating APIs directly from your schema so you don't hand-write a backend layer for basic CRUD.

  • Authentication as an integrated service
  • File storage with policy-based access
  • Realtime subscriptions to database changes
  • Serverless functions for custom logic

Architecture: Frontend/Backend -> Supabase, branching into the Postgres database (with row-level security), Auth, and Storage.

Row-level security means the database itself enforces which rows a given request may see or modify, based on who's asking -- not just application code deciding what to display.

A genuinely critical distinction sits alongside this: client-accessible keys are restricted by row-level security, while server-only secret keys bypass it entirely.

Row-Level Security
A database-level security feature where access rules are enforced per row based on who is making the request, so the database itself -- not just application code -- controls which rows a given query can see or change.
text
SUPABASE ARCHITECTURE
---------------------
                     +----------------------------+
                     |          Supabase          |
Frontend / Backend ->|  Postgres DB (Row-Level    |
                     |  Security) | Auth | Storage |
                     +----------------------------+

Connect it to a real scenario

A client-accessible key is safe in frontend code specifically because row-level security policies constrain what it can see or change -- as long as policies are configured correctly.

A service-role or secret key bypasses those policies entirely and is intended only for trusted server-side code that has already done its own authorization checks.

Start closed

Treat every new table's default access as closed to any client-accessible key.

Write a specific policy

Add a row-level security policy describing exactly who can select, insert, update, or delete which rows.

Test the boundary

Deliberately try to access data you shouldn't be able to, confirming the policy actually blocks it.

Because dashboard specifics evolve, the durable practice is starting closed and opening deliberately, rather than starting open and hoping nothing risky gets exposed.

Client-accessible keys are not server secrets

A key meant for browser use (restricted by security policies like row-level security) and a server-only secret key (which bypasses those restrictions) are not interchangeable. Using a server-only secret in browser-exposed code is a real, serious security risk -- it can hand any visitor full access to your database.

Try the working example

javascript
function checkKeyUsage(usage) {
  const { keyType, context } = usage;
  const risky = keyType === "service-role" && context === "browser";
  return risky ? "RISKY: service-role key exposed to browser" : "safe";
}

const scenarios = [
  { label: "anon key in frontend JS", keyType: "public-anon", context: "browser" },
  { label: "service-role key in frontend JS", keyType: "service-role", context: "browser" },
];

for (const s of scenarios) {
  console.log(`${s.label} -> ${checkKeyUsage(s)}`);
}
You should see
anon key in frontend JS -> safe
service-role key in frontend JS -> RISKY: service-role key exposed to browser

5-minute try-it

For a table storing private user notes, describe in plain language what a row-level security policy would need to say so users can only see their own notes.

One important caution

Leaving a table's row-level security unconfigured or disabled while still exposing a client-accessible key, allowing any visitor to read or modify all rows.

Embedding a service-role or secret key in frontend code, bypassing all row-level security protections entirely.

PostgreSQL Documentation: Row Security PoliciesCloud Providers & Platforms

Easy traps

  • Leaving a table's row-level security unconfigured or disabled while still exposing a client-accessible key, allowing any visitor to read or modify all rows.
  • Embedding a service-role or secret key in frontend code, bypassing all row-level security protections entirely.
  • This course teaches the provider/platform landscape at comparison level only -- for hands-on depth on AWS, Docker, CI/CD, Firebase, or deployment fundamentals, continue to the AWS Fundamentals, Docker, CI/CD, Firebase, or Cloud & Deployment tutorials.

Exercise

For a table storing private user notes, describe in plain language what a row-level security policy would need to say so users can only see their own notes.

You'll know it worked when: anon key in frontend JS -> safe service-role key in frontend JS -> RISKY: service-role key exposed to browser