Quase todas as reescritas de SaaS que nos chamaram a salvar remontam às mesmas três palavras pronunciadas pela equipa original logo no primeiro mês: «acrescentamos isso mais tarde». A multilocação, o controlo de acesso por papéis, a faturação a sério. Dá a impressão de que são coisas que se acrescentam depois de já se terem clientes. É exatamente o contrário — são a própria forma do edifício, e não se podem mudar os alicerces depois de erguidas as paredes sem demolir tudo.
Construímos plataformas que hoje funcionam em mais de 40 países sobre uma única base de código. A razão que o tornou possível é tão aborrecida quanto unânime: a locação, o acesso e a faturação foram decididos logo no primeiro dia, antes da primeira funcionalidade. Eis o aspeto dessas decisões e o que custa adiá-las.
01Por que razão as equipas a evitam (e por que razão é uma armadilha)
A pressão é real. Tem um único cliente-piloto, uma demonstração para a semana que vem e um backlog de funcionalidades que se parecem mesmo com o produto. A multilocação é invisível para esse primeiro cliente — ele não a consegue ver, por isso parece um adorno supérfluo. A equipa constrói então uma aplicação de locatário único «por agora» e promete generalizá-la mais tarde.
A armadilha é que «locatário único por agora» deixa escapar um pressuposto para cada camada: o de que existe exatamente uma única organização no mundo. Esse pressuposto acaba nas suas consultas, na sua autenticação, nas suas caches, nas suas tarefas em segundo plano, nos seus caminhos de ficheiros. Removê-lo mais tarde não é uma refatoração — é uma reescrita, porque o pressuposto não está num único sítio, está em toda a parte.
Acrescentar a locação logo no primeiro dia custa-lhe talvez duas semanas de arquitetura e disciplina. Acrescentá-la no segundo ano — depois de ter clientes reais, dados reais e expectativas reais de disponibilidade — é uma reescrita de vários meses sob carga, com uma migração de dados que não tem o direito de falhar. O trabalho não desaparece se o adiar. Acumula-se.
02O locatário é a primeira coluna
A nossa regra é simples: cada linha que pertence a um cliente leva um tenant_id, e não existe nenhum caminho de código capaz de fazer uma consulta sem ele. Não uma convenção de que as pessoas se lembram — uma restrição que a base de dados e a framework impõem, de modo que esquecê-la se torne impossível, em vez de apenas desaconselhado.
A versão mais limpa que usamos apoia-se na própria base de dados. As políticas de segurança ao nível das linhas significam que a fronteira entre locatários é imposta uma camada abaixo do código aplicacional, onde um bug de ORM ou uma cláusula WHERE esquecida não consegue fazer escapar os dados de um cliente para outro. A aplicação define o locatário atual na ligação; a base de dados recusa-se a devolver qualquer outra coisa.
-- a fronteira vive abaixo da app, não dentro dela ALTER TABLE orders ENABLE ROW LEVEL SECURITY; CREATE POLICY tenant_isolation ON orders USING (tenant_id = current_setting('app.tenant')::uuid); -- a app define o locatário por pedido; uma cláusula WHERE -- esquecida devolve agora zero linhas em vez dos dados de outrem SET app.tenant = 'a91f…'; SELECT * FROM orders; -- apenas as encomendas deste locatário, sempre
Esta única decisão retira da sua lista de preocupações, e de forma permanente, toda uma categoria de bugs catastróficos — a fuga de dados entre locatários. São os dois dias de trabalho de maior alavancagem de todo o projeto.
O bug mais dispendioso em SaaS é aquele que mostra a um cliente os dados de outro cliente. Conceba a sua arquitetura para que ele não possa acontecer, não para que seja improvável.
— Sobre o isolamento como restrição03O RBAC não é uma página de definições
O segundo «mais tarde» que se transforma em reescrita é o controlo de acesso. As equipas entregam com um mundo implícito de dois papéis — admin e utilizador — codificado de forma rígida em instruções if espalhadas por toda a base de código. Depois, um cliente de grande dimensão pede um papel «só faturação», ou um «auditor só de leitura», e descobre lógica de permissões em duzentos sítios.
Modelamos as permissões como dados desde o início: os papéis, as permissões e as atribuições entre eles vivem em tabelas, e cada ação protegida coloca uma pergunta a uma única autoridade central: «pode este ator fazer esta coisa sobre este recurso, neste locatário?». Acrescentar um papel torna-se uma linha, não um lançamento. É isto que permite a uma plataforma dizer sim ao organigrama do cliente de grande dimensão sem tocar no código aplicacional.
- As permissões são verbos sobre recursos —
invoice:read,invoice:void— não níveis vagos como «gestor». - Os papéis são conjuntos de permissões que um locatário pode compor, de modo que dois clientes podem entender coisas diferentes por «admin».
- Cada verificação passa por uma única porta. Uma lógica de autorização num único sítio é auditável; instruções
ifespalhadas são um passivo.
04A faturação é um produto, não canalização
A faturação é onde «acrescentamos isso mais tarde» mais dói, porque, no momento em que a acrescenta, tem clientes com acordos selados por um aperto de mão, dados incoerentes sobre quem deve o quê, e nenhum conceito limpo de subscrição. Recuperar a faturação é reconciliar dinheiro, e é o único lugar onde um bug não é apenas incómodo — é um reembolso, um litígio ou um problema de conformidade.
Concebemos o modelo de faturação ao mesmo tempo que o modelo de locatário: planos, subscrições, utilização, faturas, e o ciclo de vida que os liga. Mesmo que os primeiros clientes sejam faturados manualmente, o modelo de dados está presente desde o primeiro dia, de modo que ativar mais tarde planos em autosserviço é uma funcionalidade, não uma migração de todo o histórico da sua receita.
Uma base de código, um modelo de implementação, muitos locatários.
Nenhum fork por cliente para manter ou deixar divergir.
Isolamento imposto ao nível da base de dados, não por convenção.
05Quarenta países, uma única base de código
Chegar a mais de 40 países dá a impressão de ser uma história de escalabilidade. É, na verdade, uma história de configuração. A plataforma não tem ramos de código específicos de cada país — tem um modelo de locatário suficientemente rico para exprimir como dados aquilo que difere de uma região para outra: moeda, regras fiscais, idioma, formatos de data, menções legais numa fatura.
Quando a fronteira entre «código» e «configuração» é traçada corretamente desde o primeiro dia, um novo país é uma tarefa de onboarding, não um projeto de engenharia. Quando é mal traçada, cada novo mercado é um fork, e em menos de um ano está a manter uma dúzia de versões subtilmente diferentes da mesma aplicação e a entregar cada correção uma dúzia de vezes. O resultado «uma única base de código» decorre de decisões tomadas antes do primeiro cliente.
O benefício de fazer isto desde o primeiro dia não é visível no primeiro mês — é visível no terceiro ano, quando entrega uma funcionalidade uma única vez e 40 países a recebem em simultâneo, enquanto o seu concorrente de locatário único ainda anda a fundi-la no seu sétimo fork de cliente.
06A checklist do primeiro dia
Se está a iniciar uma plataforma SaaS este trimestre, eis as decisões a tomar antes de escrever a mais pequena funcionalidade — não porque sejam urgentes, mas porque são irreversíveis:
- Coloque um
tenant_idem tudo e imponha-o abaixo da aplicação. Segurança ao nível das linhas ou equivalente. Torne uma consulta entre locatários impossível, não improvável. - Modele as permissões como dados. Papéis e atribuições em tabelas, uma única porta de autorização central. Acrescentar um papel deveria ser uma linha.
- Construa cedo o modelo de dados de faturação. Planos, subscrições, faturas — mesmo que fature à mão no início. Não recupere o dinheiro à posteriori.
- Separe o código da configuração. Tudo o que varia consoante o cliente ou a região é um dado. O país número 41 deveria ser um formulário de onboarding.
- Escreva primeiro o caminho de aprovisionamento de locatário. Criar corretamente um novo locatário, com valores predefinidos sensatos, é a sua operação mais executada. Automatize-a desde o primeiro dia.
Nada disto é exótico. São algumas semanas de disciplina à partida em troca de nunca ter de fazer a reescrita. As equipas que chegam a 40 países sobre uma única base de código não tiveram sorte — simplesmente recusaram-se a dizer «mais tarde» a respeito das três coisas que não podem ser acrescentadas mais tarde.

