---
term: 'Segurança em Nível de Linha (RLS)'
seoTitle: 'O que é Segurança em Nível de Linha (RLS)? Guia Completo'
headline: 'O que é Segurança em Nível de Linha (RLS)?'
slug: seguranca-em-nivel-de-linha
category: database
shortDefinition: '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.'
relatedTerms:
  - access-control-lists-acl
  - class-level-permissions-clp
  - role-based-access-control-rbac
  - tenant-isolation
  - data-layer-vs-application-layer-security
contrastsWith:
  - class-level-permissions-clp
faq:
  - question: 'O que é segurança em nível de linha em termos simples?'
    answer: '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.'
  - question: 'Como funciona a segurança em nível de linha?'
    answer: '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.'
  - question: 'Qual a diferença entre USING e WITH CHECK?'
    answer: '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.'
  - question: 'Quem pode contornar a segurança em nível de linha?'
    answer: '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.'
  - question: 'Segurança em nível de linha prejudica a performance?'
    answer: '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.'
  - question: 'Qual a diferença entre RLS e filtragem na aplicação?'
    answer: '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.'
  - question: 'Como o RLS funciona com connection pooling?'
    answer: '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.'
  - question: 'Como testar políticas de segurança em nível de linha?'
    answer: '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.'
codeLanguages: [javascript, dart, swift, kotlin]
externalAuthorities:
  - name: 'PostgreSQL Row Security Policies'
    url: 'https://www.postgresql.org/docs/current/ddl-rowsecurity.html'
  - name: 'PostgreSQL CREATE POLICY reference'
    url: 'https://www.postgresql.org/docs/current/sql-createpolicy.html'
  - name: 'Row-Level Security and Multi-Tenancy on MongoDB (Back4app Engineering)'
    url: 'https://www.back4app.com/multi-tenant-mongodb-row-level-security'
  - name: 'Backend security documentation'
    url: 'https://docs.parseplatform.org/parse-server/guide/#security'
cta:
  title: 'Adicione segurança em nível de linha ao seu MongoDB'
  text: 'O Back4app aplica acesso por linha em um banco de documentos de fábrica: todo objeto carrega uma ACL, papéis agrupam usuários e a plataforma verifica os dois em toda requisição — todo SDK, toda API, o dashboard também. Nenhuma política para escrever à mão, nenhuma cláusula WHERE para esquecer.'
  linkText: 'Comece grátis'
  linkUrl: 'https://www.back4app.com/signup'
author: 'Back4app Engineering'
publishedDate: '2026-08-21'
translationKey: row-level-security
---

**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

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

## RLS em dez linhas de SQL

```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:**

```javascript
// 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
```

**Flutter:**

```dart
// Flutter / Dart — Back4app Flutter SDK
// Row-level security as data: this row is readable by its owner, period
final user = await ParseUser.currentUser() as ParseUser;
final acl = ParseACL(owner: user); // owner-only, on the row itself

final note = ParseObject('Note')
  ..set('text', 'Q3 salary planning')
  ..setACL(acl);
await note.save(); // other users' queries never return this row
```

**Swift:**

```swift
// iOS / Swift — Back4app Swift SDK
// Row-level security as data: this row is readable by its owner, period
var note = Note()
note.text = "Q3 salary planning"
note.ACL = try ParseACL.defaultACL() // owner-only, on the row itself
note.save { result in
  if case .success = result {
    print("saved — other users' queries never return this row")
  }
}
```

**Kotlin:**

```kotlin
// Android / Kotlin — Back4app Android SDK
// Row-level security as data: this row is readable by its owner, period
val note = ParseObject("Note").apply {
  put("text", "Q3 salary planning")
  acl = ParseACL(ParseUser.getCurrentUser()) // owner-only, on the row itself
}
note.saveInBackground { e ->
  if (e == null) Log.d("Notes", "saved — invisible to every other user")
}
```

## O que o engine faz com uma consulta

```mermaid
flowchart LR
  accTitle: Como a segurança em nível de linha filtra uma consulta
  accDescr: 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.
  Q["SELECT * FROM invoices<br/>(mesma consulta, qualquer usuário)"] --> P["Predicado da política<br/>aplicado por linha, primeiro"]
  P --> A["Tenant A vê<br/>só as linhas do tenant A"]
  P --> B["Tenant B vê<br/>só as linhas do tenant B"]
```

## USING vs. WITH CHECK, permissivas vs. restritivas

| Conceito | Governa | Regra de bolso |
| --- | --- | --- |
| `USING` | O que existe para você: leituras e linhas elegíveis para update/delete | "Posso ver isto?" |
| `WITH CHECK` | O 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 concede | Conceder acesso |
| Políticas restritivas | Somadas com AND — todas precisam passar | Impor limites obrigatórios |

Duas regras de composição que valem memorizar da [referência do PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html): 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 engine | Mecanismo |
| --- | --- |
| PostgreSQL (9.5+) e derivados | `CREATE 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 nuvem | Políticas de acesso por linha, no dialeto de cada fornecedor |
| Bancos de documentos | Nã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](https://www.back4app.com/multi-tenant-mongodb-row-level-security).

## 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 tabelas | O banco tem exatamente um chamador confiável |
| Algo além do app toca o banco | Sem ferramentas de BI, sem SQL de admin, sem um segundo serviço |
| Filtro esquecido significa violação, não bug | O escopo é conveniência, não segurança |
| O compliance quer prova na camada de dados | Os dados não são sensíveis |
| Você quer a fronteira testada uma vez, centralmente | Você 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](https://docs.parseplatform.org/parse-server/guide/#security) — 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ê.
