Separação
A fronteira que a base de dados mantém, não o código
Todos os CRM dizem ser multi-tenant. A afirmação é barata; o que importa é que camada está a segurar a linha. Se a resposta for "a nossa aplicação adiciona sempre o filtro correto", então a garantia é apenas tão boa quanto o programador menos descansado que alguma vez escreveu uma query.
O iKonekt foi multi-tenant desde a sua primeira migração em vez de adaptado depois, o que parece uma jactância e é na verdade uma admissão: adaptar isso depois é quase impossível de fazer de forma convincente, e todos os que tentaram têm uma história para contar.
A separação vive na base de dados. Cada uma das vinte e seis tabelas transporta o tenant a que pertence, e a política que o verifica corre em cada leitura e em cada escrita, completamente abaixo da aplicação. Uma query que esquece a fronteira não devolve os clientes de outra pessoa. Não devolve nada.
Segurança ao nível da linha, forçada
Não é uma convenção, nem uma regra de revisão de código. A base de dados recusa. Setenta e duas políticas, escritas uma a uma em vez de geradas — porque uma política gerada é uma política que ninguém leu.
Chaves compostas
Um registo filho referencia o seu tenant e o seu pai em conjunto, como um par. Um identificador perdido da empresa errada não se resolve — simplesmente não é uma referência válida.
Nunca há tenant predefinido
Um pedido sem âmbito não se transforma silenciosamente num pedido para o tenant zero. Falha antes de chegar à base de dados. Não existe um modo "unscoped" para esquecer de desligar.
O erro que não se pôde anunciar
Enquanto o trabalho de multi-tenancy estava a ser feito, a maioria dos erros era ruidosa. Dá a duas empresas o mesmo domínio de cliente e a base de dados objeta imediatamente, com um código de erro e um stack trace; corriges antes do almoço.
Um não objetou. Uma tabela de substituições editáveis de prompts era indexada apenas pelo tipo do prompt — não por tipo e tenant. Uma segunda empresa a editar a sua própria cópia teria silenciosamente sobrescrito a da primeira empresa, através de SQL perfeitamente válido, sem erro, sem aviso, e sem teste a falhar. Foi encontrado ao ler todos os índices únicos restantes depois de alterar uma chave, um a um, na suspeita de que os ruidosos tinham companhia.
Mencionamo-lo porque é a forma honesta deste trabalho. A separação não é uma funcionalidade que se liga; é um hábito de ler as partes aborrecidas do esquema partindo do princípio de que algo aí discorda de ti.
Os testes, para registo: 942 deles, executados contra uma base de dados reconstruída do zero a cada alteração. Não estão lá para provar que o design é engenhoso. Estão lá porque o modo de falha deste design em particular é silencioso, e falhas silenciosas precisam de alguém a gritar em seu nome.
O que a separação dá a uma pessoa normal
- Um grupo pode gerir várias empresas numa só instalação, e um vendedor de uma nunca verá um cliente de outra — não por política, mas por construção.
- Um programa de parceiros, um conjunto de prompts, uma reivindicação sobre um cliente: tudo com âmbito por empresa, para que a configuração de um tenant não se torne a de todos.
- Um pedido de eliminação é honrado dentro de uma fronteira em vez de através de uma pilha partilhada, e é isso que torna possível responder com honestidade.
- E ninguém tem de se lembrar de nada disto. Esse é o ponto — uma garantia que depende de ser lembrada não é uma garantia.
Mais uma linha que não é sobre bases de dados
Cada serviço irmão da família tem a sua própria credencial com nome. Nada fala com uma credencial partilhada, por isso nenhum serviço pode agir acidentalmente como outro — uma pequena disciplina que veio diretamente de já termos tido um token partilhado e de não termos gostado da experiência.
É o mesmo instinto que a regra da base de dados. Torna o errado impossível em vez de desencorajado, e gastas a tua atenção nos clientes em vez de na vigilância.
- 126 tabelasCada uma carrega o seu tenant, com a verificação forçada.
- 272 políticasEscritas individualmente, para que cada uma tenha sido lida por uma pessoa.
- 3942 testesContra uma base de dados reconstruída do zero, a cada alteração.
- 40 tenants por defeitoUm pedido sem âmbito nunca chega aos dados.
Medido na build em produção

«A nossa aplicação filtra sempre por empresa.»
«Sempre» está a fazer muito trabalho nessa frase.
Move a fronteira para dentro da base de dados e uma cláusula WHERE esquecida devolve nada em vez dos clientes de outra pessoa. Um ecrã vazio é uma falha melhor do que uma apresentação embaraçosa.
Para grupos com várias marcas →