Skip to main content

Arquitectura Multi-tenant

🏢 ¿Qué es Multi-tenancy?

La arquitectura multi-tenant permite que una sola instancia del CDP sirva a múltiples organizaciones (tenants) de forma aislada y segura, cada una con sus propios datos, configuraciones e integraciones.

🏗️ Diseño de Arquitectura

Aislamiento de Datos

-- Todas las tablas incluyen tenant_id
CREATE TABLE customers (
id SERIAL PRIMARY KEY,
tenant_id INTEGER NOT NULL,
email VARCHAR(255),
created_at TIMESTAMP,
CONSTRAINT fk_tenant FOREIGN KEY (tenant_id) REFERENCES tenants(id)
);

-- Índices optimizados por tenant
CREATE INDEX idx_customers_tenant ON customers(tenant_id, email);

Row-Level Security (RLS)

-- Política de seguridad automática
CREATE POLICY tenant_isolation ON customers
FOR ALL TO app_role
USING (tenant_id = current_setting('app.current_tenant_id')::INTEGER);

ALTER TABLE customers ENABLE ROW LEVEL SECURITY;

🔐 Modelo de Tenants

Tipos de Tenant

1. Enterprise Tenant

  • Características: Multi-marca, múltiples integraciones
  • Ejemplos: Grupo Nerdistan (Chelsea, MundoJuguete, Seven Sport)
  • Recursos: Dedicados, SLA premium

2. Business Tenant

  • Características: Single-brand, integraciones básicas
  • Ejemplos: Marca individual con VTEX
  • Recursos: Compartidos, SLA estándar

3. Trial Tenant

  • Características: Evaluación, datos limitados
  • Duración: 30 días
  • Recursos: Limitados, sin SLA

Configuración de Tenant

{
"id": 56,
"name": "Chelsea",
"slug": "chelsea",
"type": "enterprise",
"plan": "premium",
"status": "active",
"settings": {
"timezone": "America/Argentina/Buenos_Aires",
"currency": "ARS",
"language": "es",
"data_retention_days": 2555,
"max_customers": 1000000,
"max_api_calls_day": 100000
},
"integrations": [
{
"type": "vtex",
"account": "chelseaio",
"environment": "vtexcommercestable",
"status": "active"
}
],
"features": {
"rfm_analysis": true,
"clv_prediction": true,
"churn_detection": true,
"email_automation": true,
"api_access": true,
"custom_reports": true
}
}

📊 Tenants Activos

Distribución Actual

Tenant IDNombreTipoClientesEstadoÚltima Sync
56ChelseaEnterprise65,226Activo2h ago
57MundoJugueteEnterprise45,282Activo1h ago
58Seven SportEnterprise29,707Activo3h ago
59Test BrandBusiness8,521Activo6h ago
60Demo AccountTrial1,286Activo12h ago

Métricas Globales

{
"total_tenants": 5,
"total_customers": 149522,
"active_integrations": 8,
"total_api_calls_today": 45230,
"storage_used_gb": 127.5,
"processing_time_avg_minutes": 15.3
}

🚀 APIs de Tenant Management

Listar Tenants

GET /api/v2/tenants

Respuesta

{
"success": true,
"data": [
{
"id": 56,
"name": "Chelsea",
"slug": "chelsea",
"type": "enterprise",
"status": "active",
"customer_count": 65226,
"last_sync": "2024-09-16T17:30:00Z",
"integrations": [
{
"type": "vtex",
"status": "active",
"last_sync": "2024-09-16T17:30:00Z"
}
]
}
]
}

Obtener Tenant Específico

GET /api/v2/tenants/56

Crear Nuevo Tenant

POST /api/v2/tenants
{
"name": "Nueva Marca",
"slug": "nueva-marca",
"type": "business",
"settings": {
"timezone": "America/Argentina/Buenos_Aires",
"currency": "ARS",
"language": "es"
}
}

Actualizar Configuración

PUT /api/v2/tenants/56/settings
{
"max_customers": 2000000,
"max_api_calls_day": 200000,
"features": {
"advanced_analytics": true
}
}

🔌 Gestión de Integraciones

Integraciones por Tenant

GET /api/v2/tenant-integrations?tenant_id=56

Tipos de Integración Soportados

VTEX E-commerce

{
"type": "vtex",
"config": {
"account_name": "chelseaio",
"environment": "vtexcommercestable",
"app_key": "vtexappkey-chelseaio-XXXXX",
"app_token": "encrypted_token",
"sync_frequency": "hourly"
}
}

MercadoLibre

{
"type": "mercadolibre",
"config": {
"client_id": "ml_client_id",
"client_secret": "encrypted_secret",
"refresh_token": "encrypted_token",
"site_id": "MLA"
}
}
{
"type": "google_ads",
"config": {
"customer_id": "1234567890",
"developer_token": "encrypted_token",
"client_id": "oauth_client_id",
"client_secret": "encrypted_secret"
}
}

Facebook Ads

{
"type": "facebook_ads",
"config": {
"access_token": "encrypted_token",
"ad_account_id": "act_1234567890",
"app_id": "facebook_app_id"
}
}

Crear Nueva Integración

POST /api/v2/tenant-integrations
{
"tenant_id": 56,
"integration_type": "vtex",
"account_name": "nueva-cuenta",
"environment": "vtexcommercestable",
"app_key": "vtexappkey-nueva-cuenta-XXXXX",
"app_token": "token_aqui",
"auto_sync": true,
"sync_frequency": "daily"
}

Validar Credenciales

POST /api/v2/tenant-integrations/validate/vtex
{
"account_name": "chelseaio",
"app_key": "vtexappkey-chelseaio-XXXXX",
"app_token": "token_here",
"environment": "vtexcommercestable"
}

🔄 Sincronización de Datos

Estrategias de Sync

Real-time (Webhooks)

  • VTEX: Order hooks, customer updates
  • Latencia: <1 minuto
  • Uso: Eventos críticos

Scheduled Batch

  • Frecuencia: Hourly, daily, weekly
  • Latencia: Configurable
  • Uso: Datos históricos, reportes

Manual Trigger

  • On-demand: Via API o dashboard
  • Uso: Troubleshooting, testing

Estado de Sincronización

GET /api/v2/tenant-integrations/56/sync-status
{
"tenant_id": 56,
"integrations": [
{
"type": "vtex",
"status": "syncing",
"last_sync": "2024-09-16T17:30:00Z",
"next_sync": "2024-09-16T18:30:00Z",
"records_synced": 1250,
"errors": 0,
"sync_duration_minutes": 15.3
}
],
"overall_status": "healthy"
}

Trigger Manual Sync

POST /api/v2/tenant-integrations/56/sync
{
"integration_types": ["vtex", "google_ads"],
"sync_type": "incremental",
"priority": "high"
}

📊 Monitoring Multi-tenant

Health Dashboard

-- Vista de salud por tenant
SELECT
t.id,
t.name,
COUNT(c.id) as customer_count,
ti.last_sync,
CASE
WHEN ti.last_sync > NOW() - INTERVAL '2 hours' THEN 'healthy'
WHEN ti.last_sync > NOW() - INTERVAL '1 day' THEN 'warning'
ELSE 'critical'
END as health_status
FROM tenants t
LEFT JOIN customers c ON t.id = c.tenant_id
LEFT JOIN tenant_integrations ti ON t.id = ti.tenant_id
GROUP BY t.id, t.name, ti.last_sync;

Alertas Automáticas

# Monitoreo de salud por tenant
def monitor_tenant_health():
for tenant in get_all_tenants():
# Check sync delays
if tenant.last_sync < datetime.now() - timedelta(hours=6):
alert_sync_delay(tenant.id)

# Check API rate limits
if tenant.api_calls_today > tenant.max_api_calls * 0.9:
alert_api_limit(tenant.id)

# Check storage usage
if tenant.storage_used > tenant.storage_limit * 0.8:
alert_storage_usage(tenant.id)

🔐 Seguridad y Aislamiento

Encryption at Rest

  • Customer Data: AES-256 encryption
  • Credentials: Separate keystore
  • Backups: Encrypted backups

Network Isolation

  • VPC: Isolated networks per tenant type
  • API Gateway: Rate limiting per tenant
  • Database: Connection pooling with tenant context

Access Control

# Middleware de autenticación
@require_tenant_access
def api_endpoint(tenant_id):
# Verificar que usuario tiene acceso al tenant
if not user_has_tenant_access(current_user, tenant_id):
raise Forbidden("Access denied to tenant")

# Set tenant context para queries
set_tenant_context(tenant_id)

# Proceder con lógica de negocio
return process_request()

📈 Escalabilidad

Horizontal Scaling

  • Read Replicas: Por región geográfica
  • Sharding: Por tenant_id ranges
  • Caching: Redis per tenant

Resource Allocation

# Límites por tipo de tenant
TENANT_LIMITS = {
'trial': {
'max_customers': 1000,
'max_api_calls_day': 1000,
'storage_gb': 1,
'processing_priority': 'low'
},
'business': {
'max_customers': 100000,
'max_api_calls_day': 10000,
'storage_gb': 10,
'processing_priority': 'normal'
},
'enterprise': {
'max_customers': 10000000,
'max_api_calls_day': 100000,
'storage_gb': 100,
'processing_priority': 'high'
}
}

🔮 Roadmap Multi-tenant

Q4 2024

  • Tenant self-service portal
  • Advanced billing integration
  • Cross-tenant analytics (aggregated)
  • White-label dashboard

Q1 2025

  • Geographic data residency
  • Advanced RBAC per tenant
  • Custom domain support
  • API rate limiting per user

💡 Tip: La arquitectura multi-tenant permite escalar eficientemente, pero requiere cuidadoso diseño de seguridad y aislamiento. Cada tenant debe sentirse como si tuviera su propia instancia dedicada.