Impondo limites de planos: backend, bloqueio na UI e verificações
Impor limites de plano mantém paywalls confiáveis. Compare regras no backend, bloqueios na UI e verificações em segundo plano, além de uma checklist simples para implantação.

O que dá errado quando os limites são aplicados no lugar errado
Limites de plano normalmente significam uma de quatro coisas: quantas pessoas podem usar o produto (assentos), quanto dado você pode armazenar (registros, linhas, arquivos), quanto você pode fazer (requisições, execuções, mensagens) ou o que você pode acessar (recursos como exportações, integrações ou papéis avançados).
Os problemas começam quando esses limites são aplicados no lugar mais fácil de construir, não no lugar certo para confiar. Um padrão comum é: a UI parece bloqueada, então todo mundo assume que está bloqueada. Mas “parecia bloqueada” não é o mesmo que “foi bloqueada”.
Se um limite é aplicado apenas na interface, qualquer pessoa muitas vezes pode contorná-lo acionando a mesma ação de outra forma. Pode ser tão simples quanto um favorito antigo, uma automação importada, um cliente móvel ou uma chamada direta à API. Mesmo usuários bem-intencionados podem esbarrar nisso se a UI e o backend discordarem.
Veja o que normalmente acontece quando aplicar limites de plano é feito no lugar errado:
- Vazamento de receita: clientes continuam usando recursos pagos porque nada realmente os impede.
- Pico de suporte: as pessoas recebem erros confusos, ou nenhum erro, e perguntam por que a cobrança não bate com o uso.
- Atualizações confusas: usuários fazem upgrade, mas telas em cache ou verificações atrasadas ainda os bloqueiam.
- Limpeza de dados: mais tarde você precisa remover assentos extras, registros ou integrações após o fato.
Uma aplicação fraca também pode se tornar um problema de segurança. Se seu backend não verifica que uma ação é permitida pelo plano atual, um usuário pode acessar dados ou capacidades que nunca deveria ter. Por exemplo, esconder um botão “Exportar” não protege se o endpoint de exportação ainda responde. O mesmo risco aparece com convites de assentos, ações de admin e integrações premium.
Um cenário rápido e realista: um time no plano Basic está limitado a 3 assentos. A UI esconde o botão “Convidar membro” depois do terceiro usuário entrar. Mas a API de convite ainda aceita requisições, ou um job em background processa convites enfileirados mais tarde. O time acaba com 6 usuários ativos, e você agora tem uma disputa de cobrança, um cliente insatisfeito e uma política que não consegue aplicar com confiança.
Paywalls confiáveis vêm de decisões consistentes feitas no backend, com a UI servindo como orientação, não como portão.
Três camadas de aplicação, em termos simples
Aplicar limites de plano de forma confiável é menos sobre um paywall perfeito e mais sobre colocar verificações nos lugares certos. Pense nisso como três camadas que funcionam juntas: o que o usuário vê, o que o servidor permite e o que o sistema audita depois.
1) Bloqueio na UI (o que o usuário vê)
O bloqueio na UI é quando o app esconde, desabilita ou rotula ações com base no plano. Por exemplo, um botão “Adicionar colega” pode ficar desabilitado com uma observação de que o plano inclui 3 assentos.
Essa camada trata de clareza e menos cliques acidentais. Melhora a experiência, mas não é segurança. Qualquer pessoa ainda pode tentar acionar a ação chamando a API diretamente, reproduzindo requisições antigas ou usando um cliente diferente.
2) Aplicação no backend (o que é realmente permitido)
Aplicação no backend é o servidor recusando ações que excedem o plano. Deve retornar um erro claro e consistente que a UI possa tratar. Essa é a fonte da verdade.
“Fonte da verdade” significa que existe um lugar que decide, toda vez, se uma ação é permitida. Se a UI diz “sim” mas o backend diz “não”, o backend vence. Isso mantém o comportamento consistente entre web, mobile, ferramentas de admin e integrações.
3) Verificações em background (o que é verificado depois)
Verificações em background são jobs que procuram por excessos depois do fato. Elas capturam casos extremos como atualizações de cobrança atrasadas, condições de corrida (duas pessoas atualizando ou convidando ao mesmo tempo) ou uso que é contado de forma assíncrona.
As verificações em background não substituem a aplicação no backend. Elas existem para detectar e corrigir, não para decidir em tempo real.
Aqui está a maneira mais simples de lembrar as três camadas:
- Bloqueio na UI: oriente o usuário e defina expectativas
- Aplicação no backend: bloqueie a ação se ela violar as regras
- Verificações em background: detecte e corrija problemas que escaparem
Se você constrói com uma plataforma como AppMaster, mantenha a decisão da regra na lógica do backend (por exemplo, no seu Business Process), depois reflita isso na UI para uma experiência mais suave.
Aplicação no backend: a fonte da verdade para paywalls
Se você se importa em aplicar limites de plano, o backend precisa ser o árbitro. O bloqueio na UI pode esconder botões, mas não pode impedir uma chamada direta à API, uma versão móvel antiga, um script ou uma condição de corrida onde duas ações ocorrem ao mesmo tempo.
Uma regra simples mantém paywalls confiáveis: toda requisição que cria, altera ou consome algo verifica as regras antes de confirmar.
O que validar em cada requisição
Antes de executar o trabalho, verifique o contexto e o limite. Na prática, a maioria dos apps precisa do mesmo conjunto de verificações a cada vez:
- Plano: o que o tenant pode fazer agora (recursos, cotas, período)
- Papel: quem está pedindo (owner, admin, member) e quais permissões têm
- Tenant: a qual workspace ou organização a requisição pertence (sem acesso cross-tenant)
- Recurso: o que está sendo tocado (projeto, assento, arquivo, integração) e quem é o dono
- Uso: contadores atuais vs limites (assentos usados, convites pendentes, chamadas de API neste mês)
Isso também explica por que manter a lógica no servidor ajuda web e mobile a se comportarem igualmente. Uma decisão do backend significa que você não depende de dois clientes separados interpretarem regras corretamente.
Retorne erros que a UI consiga tratar
Evite falhas vagas como "Algo deu errado" ou erros genéricos 500. Quando um limite bloqueia uma ação, retorne uma resposta clara e consistente para que a UI mostre a mensagem e o próximo passo corretos.
Uma boa resposta de limite costuma incluir:
- Um código de erro específico (por exemplo,
PLAN_LIMIT_SEATS) - Uma mensagem simples que possa ser exibida ao usuário
- O limite e o uso atual (para a UI explicar a diferença)
- Uma dica de upgrade (qual plano ou add-on remove o bloqueio)
Se você está construindo com AppMaster, centralizar essas verificações é simples porque seus endpoints de API e lógica de negócio vivem em um só lugar. Coloque verificações de plano e permissões no mesmo fluxo do backend (por exemplo, em um Business Process usado por múltiplos endpoints), assim o app web e os apps nativos recebem a mesma decisão e o mesmo formato de erro sempre.
Quando o backend é a fonte da verdade, o bloqueio na UI vira uma camada de conveniência, não de segurança. Isso é o que mantém seu paywall consistente, previsível e difícil de contornar.
Bloqueio na UI: útil, mas nunca suficiente
Bloqueio na UI significa que a interface do app guia as pessoas com base no plano. Você esconde uma opção, desabilita um botão ou mostra um ícone de cadeado com uma mensagem de upgrade. Bem feito, isso torna a aplicação de limites de plano clara e justa, porque os usuários veem o que está disponível antes de clicar.
Bloquear na UI é ótimo para reduzir frustração. Se alguém no plano básico não pode exportar dados, é melhor mostrar “Exportar (Pro)” do que deixar a pessoa preencher um formulário e falhar na última etapa. Também reduz o volume de suporte, porque muitas perguntas “Por que não posso fazer isso?” são respondidas no produto.
Mas bloquear na UI não garante segurança por si só. Um usuário pode confeccionar requisições, reproduzir uma chamada de API antiga, automatizar ações ou modificar um cliente móvel. Se o backend aceitar a requisição, o limite deixou de existir, mesmo que a UI parecesse bloqueada. Por isso aplicar limites de plano ainda precisa ser validado no servidor para toda ação protegida.
Estados bloqueados que os usuários realmente entendem
Um bom estado bloqueado é específico. Em vez de “Não disponível”, diga o que está bloqueado e por quê, e o que muda se fizerem upgrade. Mantenha o texto curto e concreto.
Por exemplo: “Convites de equipe são limitados a 3 assentos no seu plano. Faça upgrade para adicionar mais assentos.” Adicione uma ação clara, como um prompt de upgrade ou uma mensagem para solicitar ao admin.
Mostre limites antes de as pessoas alcançarem
O melhor bloqueio evita surpresas. Torne o uso visível nos locais onde as decisões são tomadas, não apenas na página de cobrança.
Um padrão simples que funciona:
- Mostre um pequeno medidor como “2 de 3 assentos usados” perto da tela relevante.
- Avise cedo (por exemplo, aos 80%) para que os usuários possam planejar.
- Explique o que acontece ao atingir o limite (bloqueado, enfileirado ou cobrado).
- Mantenha a UI consistente entre web e mobile.
Se você está construindo com um construtor de UI (por exemplo, no AppMaster), tudo bem desabilitar controles e mostrar prompts de upgrade. Apenas trate o bloqueio na UI como orientação, não como aplicação. O backend ainda deve ser a fonte da verdade, e a UI deve ajudar os usuários a evitar ações que vão falhar.
Verificações em background: capturando excessos e casos extremos
Verificações em background são a rede de segurança na aplicação de limites de plano. Elas não substituem aplicação no backend ou bloqueio na UI. Capturam o que acontece entre requisições: eventos atrasados, integrações desordenadas, retries e pessoas tentando burlar o sistema.
Uma boa regra: se o usuário pode disparar (clique, chamada de API, webhook), aplique limites no backend naquele momento. Se o limite depende de totais ao longo do tempo ou dados de outros sistemas, adicione verificações em background para confirmar e corrigir.
Para que verificações em background são boas
Alguns limites são difíceis de computar em tempo real sem deixar o app lento. Jobs em background permitem medir uso e reconciliar depois, sem bloquear toda requisição.
Verificações comuns incluem:
- Medição de uso (chamadas de API diárias, exportações mensais, totais de armazenamento)
- Reconciliação de cotas (corrigir contagens após retries, deleções ou falhas parciais)
- Sinais de fraude (rajadas incomuns, falhas repetidas, muitas tentativas de convite)
- Atualizações atrasadas (provedor de pagamento confirma renovação mais tarde que o esperado)
- Limpeza de casos extremos (recursos órfãos que inflacionam o uso)
A saída desses jobs deve ser um estado de conta claro: plano atual, uso medido e flags como “over_limit” com motivo e timestamp.
Quando um job detecta excesso
É aqui que muitos paywalls parecem aleatórios. Uma abordagem previsível é decidir antecipadamente o que acontece quando o sistema detecta um excesso após o fato.
Mantenha simples:
- Pare a próxima ação que aumente uso (criar, convidar, enviar), mas não quebre a leitura de dados existentes.
- Mostre uma mensagem clara: qual limite foi excedido, qual é o número medido atual e o que fazer a seguir.
- Se permitir um período de carência, torne isso explícito (por exemplo, “3 dias para fazer upgrade” ou “até o fim do ciclo de cobrança”).
- Se for uma parada rígida, aplique-a consistentemente na web, mobile e API.
Períodos de carência funcionam bem para limites que os usuários podem exceder por acidente (como armazenamento). Paradas rígidas se encaixam em limites que protegem custos ou segurança (como assentos em um workspace regulado). A chave é consistência: a mesma regra sempre, não “às vezes funciona”.
Finalmente, notifique sem spam. Envie um alerta quando o status virar para over limit e outro quando voltar ao normal. Para equipes, notifique tanto o usuário que acionou o excesso quanto o admin da conta, para que a correção não se perca.
Passo a passo: desenhe um sistema confiável de limites de plano
Um paywall confiável começa no papel, não no código. Se você quer que aplicar limites de plano seja previsível, escreva as regras de forma que seu backend, UI e relatórios possam concordar.
1) Faça inventário de cada limite que você vende
Comece listando limites em três categorias: acesso a recurso (se pode usar ou não), limites de quantidade (quantos de algo) e limites de taxa (com que frequência). Seja específico sobre o que é contado e quando é reiniciado.
Por exemplo, “5 assentos” não é suficiente. Decida se significa usuários ativos, usuários convidados ou convites aceitos.
2) Escolha os pontos exatos de aplicação
Em seguida, marque onde cada limite deve ser verificado. Pense em termos de ações que mudam dados ou que te custam dinheiro.
- Requisições de API que criam ou atualizam registros
- Escritas no banco (o momento em que a contagem realmente muda)
- Exportações e geração de arquivos
- Integrações que disparam chamadas externas (email, SMS, pagamentos)
- Ações de admin como convites, mudanças de papel e importações em massa
Em uma plataforma no-code como AppMaster, esse mapeamento costuma virar uma checklist simples de endpoints mais os passos do Business Process que realizam ações de “criar”, “atualizar” ou “enviar”.
3) Decida parada rígida vs limite suave
Nem toda regra precisa do mesmo comportamento. Uma parada rígida bloqueia a ação imediatamente (melhor para segurança e custo). Um limite suave permite, mas sinaliza (útil para trials ou carência temporária).
Escreva uma frase por regra: “Quando X acontece e o uso é Y, faça Z.” Isso evita lógica “depende” se infiltrando.
4) Padronize erros e estados de UI correspondentes
Defina um pequeno conjunto de códigos de erro do backend e faça a UI refletir isso de forma consistente. Usuários devem ver uma mensagem clara e um próximo passo único.
Exemplo: o código de erro SEAT_LIMIT_REACHED mapeia para um estado de botão “Convidar” desabilitado, mais uma mensagem como “Você tem 5 de 5 assentos. Remova um assento ou faça upgrade para convidar mais.”
5) Registre decisões que talvez precise defender
Adicione logging básico para cada decisão de limite: quem agiu, o que tentou, uso atual, plano e o resultado. Isso é o que você usará quando um cliente disser “Fomos bloqueados mas não deveríamos ter sido” ou quando precisar auditar um excesso.
Um exemplo realista: limites de assentos com convites e upgrades
Imagine um time no plano Basic com limite de 5 assentos. Eles já têm 4 usuários ativos e querem convidar mais dois colegas. É aqui que aplicar limites precisa ser consistente entre UI, API e o trabalho de limpeza posterior.
A UI deve deixar o limite óbvio antes do usuário bater no bloqueio. Mostre “4 de 5 assentos usados” e “1 restante” perto do botão Convidar. Quando chegarem a 5 assentos ativos, desabilite Convidar e explique o motivo em linguagem simples. Isso evita a maior parte da frustração, mas é apenas uma conveniência.
Agora a parte importante: o backend deve ser a fonte da verdade. Mesmo que alguém contorne a UI (por exemplo, chamando o endpoint de convite diretamente), o servidor deve rejeitar qualquer convite que exceda o plano.
Uma verificação simples no backend para uma requisição de convite seria assim:
- Carregar o plano do workspace e o limite de assentos.
- Contar assentos ativos (e decidir se “convites pendentes” também contam).
- Se o novo convite exceder o limite, retornar um erro como “Seat limit reached” (
SEAT_LIMIT_REACHED). - Registrar o evento para visibilidade do suporte e faturamento.
Se você constrói isso no AppMaster, pode modelar Users, Workspaces e Invitations no Data Designer e então colocar a lógica em um Business Process para que todo caminho de convite passe pela mesma regra.
Verificações em background cuidam das arestas. Convites expiram, são revogados ou nunca aceitos. Sem limpeza, seu número de “assentos usados” deriva e usuários são bloqueados incorretamente. Um job agendado pode reconciliar contagens marcando convites expirados, removendo convites revogados e recalculando uso de assentos a partir do estado verdadeiro no banco de dados.
Quando o backend bloqueia um convite, o fluxo de upgrade deve ser imediato e claro. O usuário deve ver uma mensagem como: “Você atingiu 5 assentos no Basic. Faça upgrade para adicionar mais colegas.” Após o upgrade e o pagamento, duas coisas devem mudar:
- O registro do plano é atualizado (novo limite de assentos ou novo plano).
- O usuário pode tentar o mesmo convite novamente sem reenviar os detalhes.
Feito corretamente, a UI evita surpresas, o backend evita abuso e o job em background evita bloqueios falsos.
Erros comuns que tornam paywalls pouco confiáveis
A maioria dos paywalls falha por razões simples: regras espalhadas, verificações feitas cedo demais ou o app decide “ser bonzinho” quando algo dá errado. Se você quer que aplicar limites de plano se mantenha em uso real, evite essas armadilhas.
Erros que aparecem em produtos reais
- Tratar a UI como a barreira. Esconder um botão ou desabilitar um formulário ajuda usuários, mas não impede chamadas diretas à API, versões antigas do app ou automação.
- Verificar limites na primeira tela, não na ação final. Por exemplo, você avisa “1 assento restante” na página de convite, mas não re-checa quando o usuário clica em “Enviar convite.” Dois admins podem convidar ao mesmo tempo e ambos os convites passam.
- Usar dados de plano em cache sem refresh seguro. Planos mudam, renovações e upgrades acontecem constantemente. Se seu app lê “pro” de um cache com minutos de atraso, usuários podem ser bloqueados após um upgrade ou permitidos após um downgrade.
- Contar uso de forma diferente em lugares distintos. Um endpoint conta “usuários ativos”, outro conta “usuários convidados” e um job em background conta “e-mails únicos”. O resultado é comportamento aleatório que parece bug ou cobrança injusta.
- Falhar aberto em erros. Quando seu serviço de cobrança dá timeout ou sua tabela de quotas está travada, deixar a ação passar “só desta vez” convida abuso e torna auditoria impossível.
Uma maneira prática de detectar esses problemas é seguir uma ação paga de ponta a ponta e perguntar: onde é tomada a decisão final e quais dados ela usa?
Se você usa uma ferramenta como AppMaster, o risco frequentemente não está no construtor de UI em si, mas em onde a lógica de negócio vive. Coloque a verificação final dentro do Business Process do backend que realiza a ação (criar convite, enviar arquivo, gerar relatório) e deixe web e mobile apenas refletirem o que o backend permitirá.
Quando algo falha, retorne uma resposta clara “plan limit reached” e mostre uma mensagem útil, mas mantenha a regra em um só lugar para que seja consistente entre web, mobile e automação.
Verificações rápidas antes do lançamento
Antes de lançar um paywall ou uma cota, faça uma checagem com a mentalidade “como eu poderia contornar isso?”. A maioria dos problemas aparece quando você testa como um usuário avançado: múltiplas abas abertas, retries, redes lentas e pessoas fazendo upgrade ou downgrade no meio da sessão. Essas checagens tornam a aplicação de limites previsível e segura.
Verificações do backend (devem passar sempre)
Comece com a fonte da verdade: toda ação protegida deve ser permitida ou bloqueada pelo backend, mesmo se a UI esconder o botão.
- Valide toda escrita protegida no backend (criar, convidar, enviar, exportar, chamada de API).
- Faça aplicar limites no ponto da escrita, não apenas ao listar ou visualizar dados.
- Retorne um código de erro consistente para cada limite (por exemplo:
seat_limit_reached,storage_quota_exceeded). - Defina contadores de uso uma vez (o que conta, o que não conta) e fixe a janela de tempo (por dia, por mês, por ciclo de cobrança).
- Registre bloqueios com contexto: quem foi bloqueado, qual limite, uso atual, uso permitido e o caminho da requisição.
Se você está construindo no AppMaster, isso geralmente significa que a verificação fica na lógica do backend (por exemplo em um fluxo de Business Process) bem antes de o registro ser gravado ou a ação executada.
Checagens de UI e mensagens (reduzir confusão)
Bloquear na UI ainda é valioso porque previne frustração, mas deve corresponder exatamente ao comportamento do backend. Garanta que seus códigos de erro mapeiem para mensagens claras e específicas.
Um bom teste: dispare o limite de propósito e verifique se o usuário vê (1) o que aconteceu, (2) o que fazer a seguir e (3) o que não será perdido. Exemplo: “Você tem 5 de 5 assentos. Faça upgrade para convidar mais ou remova um assento primeiro.”
Testes de cenário (capturar arestas)
Execute um conjunto pequeno de testes repetíveis antes de cada release:
- Upgrade estando acima do limite: a ação deve funcionar imediatamente após o upgrade.
- Downgrade abaixo do uso atual: o app deve deixar claras as regras de acesso (bloquear novas escritas, permitir visualização, mostrar o que precisa mudar).
- Duas pessoas atingem o mesmo limite ao mesmo tempo: apenas uma deve ter sucesso se restar apenas uma vaga.
- Retries e timeouts: uma resposta falha não deve duplicar a contagem de uso por acidente.
- Rollover da janela de tempo: contadores devem resetar quando esperado, não antes nem depois.
Se tudo isso passar, seu paywall fica bem mais difícil de contornar e mais fácil de suportar.
Próximos passos: implemente com consistência e mantenha manutenível
Comece pequeno. Escolha um limite de alto valor que afete diretamente custo ou abuso (assentos, projetos, chamadas de API, armazenamento) e faça dele sua implementação “padrão ouro”. Quando esse primeiro limite estiver sólido, copie o mesmo padrão para os próximos limites em vez de inventar uma abordagem nova cada vez.
Consistência importa mais que engenhosidade. A meta é que qualquer desenvolvedor (ou você no futuro) responda rápido a duas perguntas: onde o limite é armazenado e onde ele é aplicado.
Padronize como limites funcionam
Defina um contrato simples que você reutilize em todo lugar: o que está sendo contado, qual janela de tempo se aplica (se houver) e o que o sistema deve fazer quando o limite for alcançado (bloquear, avisar ou permitir e cobrar). Mantenha as regras iguais para web, mobile e integrações.
Uma checklist leve ajuda equipes a se alinhar:
- Escolha um lugar para armazenar direitos e contadores de uso (mesmo que a UI também os mostre)
- Crie uma única verificação compartilhada “posso fazer isso?” usada por toda ação de escrita
- Decida suas mensagens de erro e códigos para que a UI responda de maneira consistente
- Registre cada negativa com plano, nome do limite e uso atual
- Adicione uma política de override de admin (quem pode contornar e como isso é auditado)
Documente seus limites em uma página que toda a equipe possa encontrar. Inclua os pontos exatos de aplicação (nomes de endpoints de API, jobs em background e telas da UI) e 2 a 3 exemplos de casos de borda.
Teste para contornos e condições de corrida
Não dependa só de testes do caminho feliz. Adicione um pequeno plano de testes que tente quebrar seu paywall: requisições paralelas tentando criar dois recursos ao mesmo tempo, clientes desatualizados que fazem retries e chamadas diretas à API que pulam a UI.
Se você constrói com AppMaster, mapeie limites de plano e contadores diretamente no Data Designer (modelo PostgreSQL) e então aplique as regras em Business Processes e endpoints de API para que tanto web quanto mobile atinjam a mesma lógica. Essa aplicação compartilhada é o que mantém paywalls previsíveis.
Por fim, comece agora com um protótipo mínimo: um limite, um caminho de upgrade e uma mensagem de excesso. Fica muito mais fácil manter o sistema quando você valida o padrão cedo e o reutiliza em todo lugar.


