A common mistake is assuming authentication automatically protects database data.
It does not.
Authentication answers:
Who is this user?
Authorization answers:
What is this user allowed to access?
Supabase RLS can help enforce the second question.
Application-Level Checks
Your application might contain logic such as:
if user.role == "admin":
show admin panel
This is useful for controlling the user interface.
But hiding a button does not secure the database.
Database-Level Protection
RLS works closer to the data.
Even if someone sends a request directly to the database API, PostgreSQL can evaluate the policy before returning or modifying rows.
Use Both Layers
A practical architecture is:
User
↓
Application Authorization
↓
Supabase API
↓
RLS
↓
PostgreSQL
The application provides a better user experience.
RLS provides another security boundary.
Role-Based Access
Applications may have roles such as:
user
manager
admin
The application can use roles to determine which screens users see.
RLS can then enforce the underlying data access rules.
Why This Matters
Imagine an admin dashboard.
The frontend may correctly hide it from normal users.
But if database access is not protected, a user could potentially attempt direct API requests.
The database should not rely on the frontend behaving correctly.
Keep Policies Understandable
Security rules become difficult to maintain when they are unnecessarily complicated.
Keep policies focused on clear requirements.
For example:
Users can read their own records.
Users can update their own records.
Admins can manage organization records.
Final Thoughts
Application-level authorization and RLS are not necessarily competing approaches.
They solve different parts of the security problem.
Use application logic for application behavior and database policies to protect the data itself.