O que é Segurança em Nível de Linha (RLS)?

Atualizado em: agosto de 2026

Segurança em nível de linha é um mecanismo de banco de dados que filtra quais linhas cada usuário pode ver ou alterar, aplicado por políticas em toda consulta. O modelo mental é uma cláusula WHERE invisível e obrigatória: a condição que você teria de lembrar em toda consulta vira uma propriedade da própria tabela — aplicada pelo engine, em todo caminho de acesso, incluindo os que o código da sua aplicação nunca vê.

Principais pontos

PerguntaResposta
O que éControle de acesso por linha, aplicado pelo próprio engine do banco
O modelo mentalUma cláusula WHERE que não pode ser esquecida
O caso de uso matadorIsolamento multi-tenant e dados por usuário, na camada que violações não conseguem pular
As letras miúdasRoles de bypass, negar por padrão, contexto de pooling — as pegadinhas são operacionais
A falha que previneUm filtro esquecido no código da aplicação = vazamento entre tenants

RLS em dez linhas de SQL

CREATE TABLE invoices (
  tenant_id uuid NOT NULL,
  total     numeric(10,2)
);

ALTER TABLE invoices ENABLE ROW LEVEL SECURITY;   -- daqui em diante: negar por padrão

CREATE POLICY tenant_isolation ON invoices
  USING      (tenant_id = current_setting('app.tenant')::uuid)   -- o que você pode ler
  WITH CHECK (tenant_id = current_setting('app.tenant')::uuid);  -- o que você pode escrever

-- Toda consulta agora se comporta como se terminasse com WHERE tenant_id = <o seu>.
-- Uma consulta que esquece o filtro retorna nada — não tudo.

A mesma garantia existe em bancos de documentos como controle de acesso na própria linha — cada objeto carrega sua ACL, e a plataforma a aplica em toda requisição:

// JavaScript / Node.js — Back4app JS SDK
// Row-level security as data: this row is readable by its owner, period
const note = new Parse.Object('Note');
note.set('text', 'Q3 salary planning');
note.setACL(new Parse.ACL(Parse.User.current())); // owner-only, on the row itself
await note.save();

// Later, any query by any user — the row exists only for its owner
const notes = await new Parse.Query('Note').find(); // others never see it

O que o engine faz com uma consulta

Como a segurança em nível de linha filtra uma consultaDois usuários diferentes rodam a mesma consulta contra uma tabela; o engine aplica o predicado da política de segurança por linha antes das condições do usuário, então cada um recebe apenas as linhas que a sua política permite.

SELECT * FROM invoices
(mesma consulta, qualquer usuário)

Predicado da política
aplicado por linha, primeiro

Tenant A vê
só as linhas do tenant A

Tenant B vê
só as linhas do tenant B

Dois usuários diferentes rodam a mesma consulta contra uma tabela; o engine aplica o predicado da política de segurança por linha antes das condições do usuário, então cada um recebe apenas as linhas que a sua política permite.

USING vs. WITH CHECK, permissivas vs. restritivas

ConceitoGovernaRegra de bolso
USINGO que existe para você: leituras e linhas elegíveis para update/delete”Posso ver isto?”
WITH CHECKO que você pode escrever: inserts e valores pós-update”Posso criar desta forma?”
Políticas permissivas (padrão)Combinadas com OR — qualquer uma que case concedeConceder acesso
Políticas restritivasSomadas com AND — todas precisam passarImpor limites obrigatórios

Duas regras de composição que valem memorizar da referência do PostgreSQL: omitir WITH CHECK reaproveita o USING para escritas, e pelo menos uma política permissiva precisa passar antes de as restritivas serem sequer consultadas — só restritivas significa que ninguém entra.

Onde o RLS é suportado

Família de engineMecanismo
PostgreSQL (9.5+) e derivadosCREATE POLICY — a implementação de referência
SQL Server (2016+)Políticas de segurança sobre funções de predicado inline (filter + block)
SQL distribuído (CockroachDB, YugabyteDB)Políticas compatíveis com PostgreSQL
Data warehouses em nuvemPolíticas de acesso por linha, no dialeto de cada fornecedor
Bancos de documentosNão baseados em política — ACLs por objeto aplicadas pela camada de plataforma

A última linha é a que interessa a este glossário: em bancos de documentos a fronteira em nível de linha tipicamente é dado na própria linha (ACLs) em vez de um predicado no engine — mesma garantia, mecanismo diferente, detalhado no artigo de engenharia do Back4app.

As pegadinhas, finalmente em um só lugar

  • Surpresas do negar por padrão. Habilitar o RLS sem nenhuma política bloqueia todo mundo, exceto o dono — metade das histórias de “o RLS derrubou a produção” é isso.
  • A matriz de bypass. Superusuários, roles com BYPASSRLS e donos de tabela pulam as políticas — defina FORCE ROW LEVEL SECURITY se o dono também é o usuário da aplicação, e audite quem tem o quê.
  • Views avaliam como o dono delas por padrão — uma view sobre uma tabela com RLS pode contorná-lo silenciosamente, a menos que criada com direitos do invocador (security_invoker no PostgreSQL).
  • Constraints vazam existência. Uma violação de unicidade ou de chave estrangeira pode revelar que uma linha invisível existe — o canal encoberto documentado; trate unicidade sobre valores protegidos de acordo.
  • Erros podem vazar valores. Expressões forjadas que falham em dados específicos (uma divisão por zero quando um valor oculto casa) exfiltram por mensagens de erro — a classe de side-channel que a documentação do SQL Server descreve.
  • Dumps e pools têm modos. Ferramentas de backup podem precisar do row security desligado para exportar tudo; poolers em modo transação precisam de contexto com escopo de transação (SET LOCAL), ou tenants sangram entre requisições.

Performance: políticas são código no hot path

Três regras cobrem a maior parte da experiência de campo: indexe toda coluna que uma política referencia (o predicado roda antes dos filtros da sua própria consulta — sem índice, é um scan); mantenha os predicados livres de joins, empurrando lookups para funções ou verificações de role; e faça funções por requisição serem avaliadas uma vez por consulta, não uma vez por linha, envolvendo-as em uma subquery escalar. Bem medido, o RLS custa um dígito percentual; mal medido, é a lentidão misteriosa em toda tabela que você protegeu.

Casos de uso comuns

  • SaaS multi-tenant. O caso canônico — isolamento de tenant aplicado abaixo da aplicação, onde um filtro esquecido não consegue virar violação.
  • Dados por usuário. Mensagens, documentos, prontuários: usuários veem as próprias linhas, ponto final.
  • Fronteiras departamentais e regionais. Vendas vê a sua região; auditores veem tudo, somente leitura — camadas de política em ação.
  • Regimes de compliance. Controle de acesso demonstrável na camada de dados, que é onde os auditores gostam.
  • Acesso analítico compartilhado. Analistas consultam réplicas de produção diretamente, vendo apenas o que a role permite — seguro porque o banco aplica, não o dashboard.

Você deveria aplicar em nível de linha? Matriz de decisão

Aplique com RLS/ACLs quando…Filtragem na aplicação pode bastar quando…
Múltiplos tenants ou usuários compartilham tabelasO banco tem exatamente um chamador confiável
Algo além do app toca o bancoSem ferramentas de BI, sem SQL de admin, sem um segundo serviço
Filtro esquecido significa violação, não bugO escopo é conveniência, não segurança
O compliance quer prova na camada de dadosOs dados não são sensíveis
Você quer a fronteira testada uma vez, centralmenteVocê gosta de auditar toda consulta para sempre

A síntese honesta das duas colunas: mantenha o escopo na aplicação pela legibilidade — e aplique no banco mesmo assim. Defesa em profundidade é o ponto inteiro.

Limitações e trade-offs

  • Políticas são invisíveis por design — o que torna depurar o “cadê minhas linhas?” uma habilidade genuína; logue o contexto de sessão primeiro.
  • Autorização complexa ultrapassa predicados. Regras que precisam de estado de workflow ou de lógica entre entidades pertencem às camadas de autorização da aplicação, com o RLS como retaguarda.
  • A superfície operacional é real. A matriz de bypass, os modos de dump e o contexto de pooling são conhecimento operacional contínuo, não configuração única.
  • Avaliação por linha é um imposto — pequeno quando bem projetado, ilimitado quando não.
  • Protege linhas, não colunas. Esconder campos é segurança em nível de coluna; combine as duas para efeito em nível de célula.

Segurança em nível de linha no Back4app

O Back4app é uma plataforma open-source de Backend as a Service (BaaS) que combina banco de dados gerenciado, APIs REST e GraphQL geradas automaticamente, autenticação, armazenamento de arquivos e funções serverless com Cloud Code. Seu modelo em nível de linha é o mecanismo de ACL-como-dado das abas acima: todo objeto carrega sua lista de acesso, papéis expressam tenants e times, e a plataforma aplica os dois em toda requisição — SDKs, REST, GraphQL e o dashboard incluídos, com as permissões em nível de classe como a camada restritiva por cima. É a garantia da cláusula WHERE obrigatória, entregue em um banco de documentos, com a lista de pegadinhas acima absorvida pela plataforma em vez de atribuída a você.

Perguntas frequentes

O que é segurança em nível de linha em termos simples?

Uma cláusula WHERE invisível e obrigatória. Você anexa políticas a uma tabela e o banco aplica as condições delas a toda consulta automaticamente — cada usuário vê e modifica apenas as linhas que a política permite, não importa a consulta que escreva ou a ferramenta que use. O filtro vive no banco, então nenhum caminho de código da aplicação consegue esquecê-lo.

Como funciona a segurança em nível de linha?

Você habilita o RLS em uma tabela e cria políticas com predicados booleanos — tipicamente comparando a coluna de dono ou de tenant da linha com o usuário atual ou uma variável de sessão. Na consulta, o engine avalia o predicado por linha antes das suas próprias condições, filtrando leituras e bloqueando escritas não permitidas. Com o RLS habilitado e nenhuma política, o padrão é negar tudo.

Qual a diferença entre USING e WITH CHECK?

Direção. USING filtra o que existe para você: linhas visíveis ao SELECT e elegíveis para UPDATE ou DELETE. WITH CHECK valida o que você escreve: linhas sendo inseridas e os novos valores após um update. Omitido o WITH CHECK, o predicado do USING vale para os dois — mas tabelas em que usuários leem amplo e escrevem estreito precisam dos dois, configurados de forma diferente.

Quem pode contornar a segurança em nível de linha?

No PostgreSQL: superusuários, roles com BYPASSRLS e — o que todo mundo esquece — o dono da tabela, a menos que você defina FORCE ROW LEVEL SECURITY. Auditar essa matriz de bypass faz parte de colocar RLS em produção; uma política perfeita não protege nada se a aplicação conecta como o dono da tabela.

Segurança em nível de linha prejudica a performance?

Pode — o predicado da política é avaliado contra as linhas candidatas em toda consulta. As mitigações são consistentes na experiência de produção: indexe as colunas que as políticas referenciam, mantenha os predicados livres de joins (use funções ou roles de lookup) e faça funções por requisição serem avaliadas uma vez por consulta, não uma vez por linha. Política sobre coluna sem índice é um table scan com crachá de segurança.

Qual a diferença entre RLS e filtragem na aplicação?

Onde vive a fronteira. A filtragem na aplicação escopa consultas no código — flexível, mas duplicada em cada caminho e ignorada por qualquer coisa que fale com o banco diretamente. O RLS aplica no engine, cobrindo todo caminho de acesso, incluindo ferramentas de admin e outros serviços. O consenso é defesa em profundidade: escope na aplicação pela clareza, aplique no banco pela segurança.

Como o RLS funciona com connection pooling?

Com cuidado. Aplicações com pool conectam como um único usuário de banco, então as políticas dependem de uma variável de sessão por requisição, e não da identidade da conexão — definida no checkout, lida pela política, resetada na devolução. Com poolers em modo transação, a configuração precisa ter escopo de transação, ou o contexto de um tenant vaza para a próxima requisição na mesma conexão. Essa interação é o bug de RLS mais comum em produção.

Como testar políticas de segurança em nível de linha?

Impersone cada role e rode as quatro operações — select, insert, update, delete — verificando tanto o que aparece quanto o que é recusado. Adicione os dois casos esquecidos: o contexto não definido (nenhuma variável de tenant deveria significar nenhuma linha, não todas) e a matriz de bypass (dono, superusuário, caminhos de replicação). O RLS conquista confiança com testes adversariais, não com a política bem escrita.

Termos relacionados

Compare com

Leitura adicional

Pronto para construir seu backend?

Comece seu projeto no Back4app em minutos — banco de dados, autenticação, APIs e Cloud Code incluídos. Sem cartão de crédito.

Escrito e revisado por Back4app Engineering, Back4app Engineering · Publicado em 2026-08-21