What is Row Level Security (RLS) and how does it protect each row of PostgreSQL?

Published on 2026-10-20 by frfrand

RLS explicado con un ejemplo de pedidos y usuarios: políticas por fila, permisos SQL, auth.uid(), service role y errores de seguridad frecuentes.

What is Row Level Security (RLS) and how does it protect each row of PostgreSQL?

Row Level Security (RLS) is a PostgreSQL feature that allows defining which rows of a table an account can read or modify according to access policies. It is especially useful when an application stores data from many users or companies in the same tables.

Imagine a table with orders from a thousand customers. Everyone can use the same application, but no one should see another person's purchases. RLS allows applying part of that separation directly where the data lives.

The cabinet example

Think of a building with a common storage room. Each customer has an identified compartment. The main door allows entering the building, but that does not mean you can open any cabinet.

In a relational database, table permissions are similar to general access to the storage room. RLS policies check which rows correspond to each identity and operation.

The metaphor is not perfect, but it helps distinguish permission to query a table and permission to query a specific row.

Does RLS replace normal permissions?

No. PostgreSQL uses object privileges and row policies. Both layers matter.

If an account does not have permission to execute SELECT on a table, adding an RLS policy does not automatically grant that privilege. And if an account has broad privileges or can bypass RLS, it is also not advisable to assume that a policy will restrict it.

In Supabase it is especially important to review which roles have permissions on exposed tables and which policies apply.

An example with an appointment application

Suppose you have a reservas table with fields id, usuario_id, fecha, and estado.

You want each person to view their own reservations, but not those of other users. A read policy can compare the authenticated user's identifier with the usuario_id field of each row.

The specific mechanism depends on how identity reaches the database. In Supabase, for example, functions like auth.uid() are used within policies.

The idea is that the database filters authorized rows, even when a request attempts to consult more information than appropriate.

What about updating or inserting information?

Policies can distinguish operations. Allowing a person to read their own reservation does not mean allowing them to change its amount, approve it on behalf of an administrator, or create it for any user.

Rules must be defined for SELECT, INSERT, UPDATE, and DELETE according to the access model.

It is also advisable to prevent a person from changing the owner of a row to gain subsequent access. The design must contemplate both existing rows and new values.

Does RLS mean I can already trust the frontend?

No. The interface still needs correct design, and the server must perform additional checks when appropriate.

RLS protects row-level operations within PostgreSQL under its rules; it does not automatically validate payments, email sends, or complex business decisions.

It is a particularly valuable layer of defense when there are APIs or SDKs that allow access to certain tables from authenticated clients.

What is service_role in Supabase?

Supabase uses a service role with elevated privileges that can bypass RLS policies. For this reason, service keys must remain on the server side and under appropriate access controls.

It is not safe to place a credential capable of bypassing policies within the public JavaScript of a website.

Nor should you confuse a project's publishable key with universal authorization: effective access depends on roles, policies, and configuration.

Common mistakes

Creating the table and forgetting about policies. Some configurations expose data if privileges allow it.

Applying only a read policy. Inserting or updating rows may require different rules.

Testing only with an administrator. If that account bypasses RLS, you might think everything works and later discover that real users cannot access or access improperly.

Not checking negative cases. Tests must confirm that client A cannot read or modify rows from client B.

How does it fit into ArduMaker?

If you deploy a PostgreSQL database on a VPS managed from ArduMaker, you can use security capabilities native to the engine, including RLS when appropriate. But configuring the server does not automatically define your application's policies: that belongs to data and permission design.

In summary: RLS helps control row-by-row access. Combined with SQL permissions, authentication, and testing, it can be an important defense for multi-user applications.

Sources: RLS in PostgreSQL · RLS in Supabase · What Supabase is for.

What is Row Level Security (RLS) and how does it protect each row of PostgreSQL?
  • RLS
  • PostgreSQL
  • Supabase
  • seguridad

On ArduMaker

  • PostgreSQL: Install PostgreSQL and manage databases, users and permissions without the command line.

Keep reading

All articles · VPS plans