Pessoalmente eu escolheria primeiro criar uma tabela para funcionalidades e depois uma tabela associando as funcionalidades com os usuário, pra facilitar pesquisas caso precise, mas não está errado se achar que é adequado para o tamanho e as funcionalidades da sua aplicação manda bala

Agradeço pela resposta, Tiago!

Você está falando sobre associar diretamente os tenants às funcionalidades?

Atualmente, meu cenário é o seguinte:

Tenant 01 está no plano Básico, que permite o cadastro de até 5 usuários por mês.

Se Tenant 01 estivesse no plano Médio, ele poderia cadastrar até 10 usuários por mês. Este padrão se repete para os outros planos, onde cada plano tem seu próprio limite de usuários que podem ser cadastrados mensalmente.

A ideia é ajustar as funcionalidades disponíveis para cada tenant com base no plano ao qual ele está associado. Ou seja, preciso ter o fluxo de Tenant -> Plano -> Funcionalidades.

Pensei também ná ideia de criar 3 tabelas, uma pra tenant, outra pra planos e remover a coluna funcionalidades de planos e criar uma tabela funcionalidades, vinculando com planos, mas acreditaria que seria consultas a mais né? Aí seria mais simples colocar o json na tabela planos diretamente

Você poderia dar mais detalhes sobre os seus dados. Você só falou sobre número de usuários. Para isso, nem precisaria de relacionamentos. Agora, vamos supor que existam mais opções. Digamos: Básico - usuários: 5 - email personalizado: false - domínio próprio: false - notas fiscais por mês: 100 - armazenamento: 100mb Prata - usuários: 10 - email personalizado: false - domínio próprio: false - notas fiscais por mês: 500 - armazenamento: 500mb Ouro - usuários:100 - email personalizado: true - domínio próprio: true - notas fiscais por mês: 1000 - armazenamento: 1gb Neste caso, essa seria a sua tabela de planos. Casa coluna era uma funcionalidade. Agora sua tabela tenant apenas precisa armazenar o id do plano.
Exato, no caso sua ideia seria adicionar colunas pra cada funcionalidade? Por exemplo tabela de planos contendo: `nome, usuarios, email_personalizado, dominio_proprio, notas_fiscais_mes, armazenamento` Enquanto a segunda opção seria: `nome, funcionalidades` - Onde funcionalidades será um json com cada coluna utilizada anteriormente, pra ficar mais flexível. E na terceira opção: Tabela planos contendo apenas o `nome`, tabela funcionalidades contendo `nome, descricao, valor` e outra tabela pra relacionar plano e funcionalidades. -- Independente das opções acima, na tabela de tenants vai haver uma coluna `plano_id` pra fazer a relação. Pra pegar a data de expiração pensei em uma tabela a parte com o nome de assinaturas onde irá conter as colunas `tenant_id, plano_id, assinatura_efetuada_em, expira_em` pra manter os logs de assinaturas.
Tudo depende das suas regras de negócio. A sugestão de colocar as funcionalidades como colunas implica em você não estar mudando o tempo todo. Porém, se você pensar bem, sempre que uma funcionalidade é lançada, você fez diversas alterações no código, no sistema, no banco, nas interfaces etc.. não tem problema nenhum incluir uma coluna a mais. A vantagem é que fica mais simples de manter e fazer as buscas. Sobre a questão dos logs das assinaturas, esse log pode ficar separado, somente como informação extra. Não necessariamente você precisaria usá-lo como registro. Para você, é mais simples ter essa informação na tabela tenant e deixar o log ser somente log. Eu só usaria outra opção diferente dessa se você viesse a ter múltiplos planos pra um mesmo cliente. Por exemplo: o cara comprou o plano intermediário e comprou uma integração fiscal e um pacote de mil notas a mais, por exemplo. Aí você se obriga a ter um relacionamento n:n. Não dá pra fazer isso usando as colunas pois elas podem variar muito entre clientes. Mas no seu caso, usar colunas para funcionalidades atende perfeitamente. Inclusive, se você quiser facilitar ainda mais, nem precisa das colunas. Você pode deixar fixo no seu código o que cada plano tem. Por exemplo, você tem uma interface IPlan e as suas classes implementam ela. Assim você deixa seu banco sem modificações por causa de inclusão de funcionalidades. Mas fica a seu critério. Tudo depende do que você planeja. As sugestões são baseadas nos dados que você passou