Sua Página de Preços É um Contrato
Os planos nascem no site, as travas nascem no código, e três meses depois os dois já não concordam. Como usar uma fonte única de verdade e um teste para que a promessa comercial bata com o sistema.
Renan Montanari
Engenheiro de Software Full-Stack
Introdução: O Contrato Que Ninguém Revisa
Sua página de preços é um contrato. E quase sempre ela mente sem ninguém perceber.
Não por má fé. Ela mente porque foi escrita em um lugar, e o sistema que deveria cumpri-la foi escrito em outro.
Como a Divergência Nasce
O caminho costuma ser sempre o mesmo:
- A tabela de planos nasce no site, escrita à mão por quem fez a landing page.
- As travas de funcionalidade nascem no código, escritas por quem construiu o sistema.
- No dia do lançamento, os dois batem.
- Três meses depois, alguém aumenta um limite no código para atender um cliente específico, ou muda um número no site durante uma promoção.
- Os dois param de concordar. E ninguém percebe.
Quem percebe é o cliente. Ele assina o plano que prometia dez usuários, cadastra o sexto e toma erro na cara.
Por Que a Conversa Fica Ruim
A partir desse momento, qualquer resposta é ruim:
- Liberar por fora: você perde o controle dos próprios limites e cada exceção vira precedente.
- Manter a trava: o cliente tem razão em reclamar, porque a sua página prometeu outra coisa.
O problema não está na decisão de negócio. Está no fato de que a promessa e a regra foram escritas separadamente.
A Solução: Uma Única Fonte de Verdade
A ideia é simples: a página de preços não deveria ter números escritos à mão. Ela deveria ler os mesmos dados que o sistema usa para liberar funcionalidades.
// Fonte única: os planos são dados, não texto espalhado
export const plans = {
starter: {
name: 'Starter',
price: 79,
limits: { users: 3, projects: 5 },
features: ['reports.basic'],
},
pro: {
name: 'Pro',
price: 199,
limits: { users: 10, projects: 50 },
features: ['reports.basic', 'reports.advanced', 'integrations'],
},
} as const;
// A página lê daqui
export function getPricingTable() {
return Object.values(plans).map(plan => ({
name: plan.name,
price: plan.price,
users: plan.limits.users,
projects: plan.limits.projects,
}));
}
// O sistema lê daqui
export function canAddUser(plan: keyof typeof plans, currentUsers: number) {
return currentUsers < plans[plan].limits.users;
}Repare no que mudou: não existe número escrito duas vezes. Se o limite do Pro muda, muda em um lugar, e o site e as travas acompanham juntos.
Um Teste Que Impede a Divergência
Centralizar ajuda, mas não impede alguém de escrever um número à mão na landing page no futuro. Por isso vale um teste automatizado que compara o que está publicado com o que o sistema permite:
import { plans, canAddUser } from '@/billing/plans';
import { renderPricingPage } from '@/web/pricing';
it('página de preços reflete os limites reais do sistema', async () => {
const html = await renderPricingPage();
for (const [key, plan] of Object.entries(plans)) {
expect(html).toContain(`${plan.limits.users} usuários`);
expect(canAddUser(key as keyof typeof plans, plan.limits.users)).toBe(false);
expect(canAddUser(key as keyof typeof plans, plan.limits.users - 1)).toBe(true);
}
});Esse teste falha no pipeline se os dois divergirem. A divergência não chega em produção porque o build quebra antes.
Se a sua estrutura não permite testar a página assim, esse é um sinal útil: a informação provavelmente está duplicada.
O Princípio Vale Para Muito Mais Coisa
Preço é só o exemplo mais visível. O mesmo padrão aparece em:
- Textos de validação escritos no frontend e no backend, com regras diferentes
- Lista de status de pedido copiada em três arquivos
- Documentação de API que não corresponde mais ao código
- Feature flags que existem no painel mas não no código, ou o contrário
Todo lugar onde a mesma informação é escrita duas vezes vai divergir com o tempo, porque as duas cópias são mantidas por pessoas diferentes, em momentos diferentes.
A pergunta nunca é se vai divergir. É quando.
Checklist: Sua Página Cumpre o Que Promete?
- Os preços e limites da página vêm de uma fonte única?
- Existe algum número de plano escrito à mão no site?
- Um teste automatizado falha se o site divergir do sistema?
- Alguém sabe quem altera um limite e onde isso precisa ser feito?
- Exceções de cliente estão registradas, em vez de escondidas no código?
Conclusão: Confira Antes Que o Cliente Confira
Abra sua página de preços agora. Escolha um limite, por exemplo o de usuários de um plano, e teste no sistema real.
Se bater, ótimo. Se não bater, você acabou de encontrar o contrato que estava quebrado sem ninguém saber.
Quer Revisar Seu Modelo de Cobrança?
Se seu SaaS tem planos, limites e promoções e você não tem certeza de que o site e o sistema contam a mesma história, posso ajudar com:
- Diagnóstico de cobrança: onde a regra de preço está duplicada ou espalhada
- Modelo de planos como dados: uma fonte única para site, travas e relatórios
- Testes de consistência: garantir que a promessa comercial bata com o código
Falar comigo