Modelo mental completo de MongoDB | Nicolás Garzón
Inicio Wiki MongoDB Modelo mental completo de MongoDB Volver a MongoDBMongoDB
Modelo mental completo de MongoDB Integra documentos, access patterns, consultas, índices, consistencia, replicación, sharding, seguridad y operación en un modelo completo de MongoDB.
Última actualización Actualizada 25 de jul de 2026
MongoDB se diseña desde el dominio y los access patterns, no desde una lista aislada de colecciones. Cada decisión —documentos, índices, consistencia, seguridad y operación— debe responder a cómo se usa el dato y cómo puede fallar.
Nota anteriorCaso práctico: pedidos e inventario Texto
Copiar problema de negocio
→ invariantes y access patterns
→ límites documentales y tipos BSON
→ queries y escrituras
→ índices y planes
→ consistencia y topología
→ seguridad y operación
→ medición y evoluciónEl modelo mental completo evita optimizar una capa mientras se rompe otra.
Antes de abrir MongoDB, escribe:
qué entidades y procesos existen;
qué reglas nunca deben violarse;
qué estados y transiciones son válidos;
quién es dueño de cada dato;
qué debe conservarse como historia;
qué se puede recalcular;
qué errores son tolerables.
Texto
Copiar stock nunca negativo
SKU único por negocio
una orden conserva el precio vendido
un usuario no accede a otro tenant
repetir un pago no duplica el cobroEstas reglas determinan índices unique, updates condicionales, snapshots, autorización e idempotencia.
Por cada operación define:
Texto
Copiar filtro + sort + projection + limit + frecuencia + consistenciaTexto
Copiar listar 20 órdenes pending
por businessId y branchId
ordenadas por createdAt DESC, _id DESCEsta descripción guía documento e índice:
JavaScript
Copiar { businessId : 1 , branchId : 1 , status : 1 , createdAt : - 1 , _id : - 1 } No diseñes un índice antes de conocer la query completa.
¿qué se lee junto?
¿qué cambia junto?
¿qué comparte lifecycle?
¿qué necesita atomicidad?
¿cómo crece?
Es apropiado cuando el dato es dependiente, acotado y se usa con el padre.
JavaScript
Copiar {
orderId,
items : [
{ productId, nameAtPurchase, quantity, unitPrice }
]
} Los items de una orden son snapshots históricos y pertenecen a ella.
Úsalas cuando el dato tiene lifecycle independiente, alta cardinalidad o acceso propio.
JavaScript
Copiar { orderId, customerId } Una referencia no crea foreign key. Debes manejar documentos missing, autorización e integridad.
Duplica deliberadamente cuando mejora una lectura y existe source of truth, política de staleness y reconciliación.
No confundas snapshot histórico con copia sincronizada.
Toda colección y array debe tener una expectativa:
Texto
Copiar items por orden: máximo 100
branches por negocio: decenas
movimientos de inventario: ilimitados → colección separadaSin límites, aparecen documentos gigantes, multikey explosion, contention y queries impredecibles.
Busca outliers, no solo promedios.
ObjectId para identificadores BSON;
Date para fechas;
Decimal128 para dinero exacto cuando aplica;
Long para enteros fuera del rango seguro de JavaScript;
Binary para bytes;
boolean para flags reales.
String 'false', boolean false, null y missing no son equivalentes.
El tipo afecta matching, sort, índices, aggregations y serialización.
Texto
Copiar input no confiable
→ validación runtime
→ lógica de dominio
→ documento persistido
→ server validationTypeScript ayuda al compilador. Mongoose aplica reglas a sus propias operaciones. $jsonSchema e índices protegen el servidor frente a otros writers.
Durante una evolución usa expand–migrate–contract y lectores compatibles con varias versiones.
MongoDB garantiza atomicidad a nivel de un documento. Aprovecha operadores:
$set;
$inc;
$push y $addToSet con límites;
filtros con preconditions;
findOneAndUpdate.
JavaScript
Copiar db. inventory. updateOne (
{
businessId,
branchId,
productId,
available : { $gte : quantity }
} ,
{
$inc : {
available : - quantity,
reserved : quantity
}
}
) ; La condición y el cambio ocurren juntos. Read-modify-write sin precondition introduce carreras.
Una transacción es razonable cuando varias escrituras acotadas deben confirmar o abortar juntas.
Texto
Copiar reservar inventario
+ crear orden
+ registrar movimientos
+ guardar outbox
→ commitMantén callbacks cortos, pasa session a cada operación y evita paralelismo o efectos externos.
El driver puede reintentar el callback; la lógica debe tolerarlo.
La red puede fallar después de que MongoDB confirme. Un timeout no significa rollback.
Usa una clave de operación protegida por índice unique:
JavaScript
Copiar { businessId : 1 , idempotencyKey : 1 } Ante retry, devuelve el resultado anterior o un conflicto si el payload cambió.
Para eventos y workers, guarda operationId y deduplica efectos.
MongoDB no comparte una transacción con email, pagos o mensajería.
Texto
Copiar transaction
→ entidad + outbox
→ commit
→ worker idempotente
→ efecto externoEl procesamiento es al menos una vez; tanto productor como consumidor deben tolerar duplicados.
Un índice intercambia memoria, disco y coste de escritura por acceso eficiente.
equality;
sort;
range;
prefix rule;
selectividad;
collation;
arrays/multikey;
projection;
distribución y tenants outlier.
ESR es una heurística, no una receta absoluta.
No crees un índice por campo ni uno gigante para todas las queries.
winning plan;
nReturned;
totalKeysExamined;
totalDocsExamined;
bounds;
FETCH;
SORT;
cardinalidad entre stages.
Texto
Copiar IXSCAN ≠ eficiente automáticamentePrueba casos típicos, vacíos, rangos amplios y outliers. Explain no reemplaza una prueba de carga ni métricas de la aplicación.
Devuelve solo campos necesarios y limita resultados. Una projection reduce red y deserialización; una covered query puede evitar leer documentos.
En Mongoose, lean() reduce hydration en Node.js, pero no cambia el plan del servidor.
Usa cursor pagination con sort estable en lugar de skip profundo.
Define qué confirmación espera una escritura: nodo, journal, mayoría y timeout.
Define la garantía de visibilidad de la lectura.
Define qué miembros pueden atenderla.
No elijas una configuración global por costumbre. Una respuesta de catálogo, un pago y un reporte tienen necesidades distintas.
Retryable writes y transaction retries ayudan con fallos transitorios, pero no convierten cualquier operación en exactamente una vez.
transient transaction error;
unknown commit result;
duplicate key;
write concern error;
network timeout;
server selection.
No añadas un retry genérico alrededor de toda la aplicación.
Un replica set ofrece copias, elections y base para transactions/Change Streams.
delete válido;
corrupción lógica;
ransomware;
credenciales comprometidas.
Necesitas backups independientes y restore tests.
Observa lag, oplog window, majority y estado de todos los miembros.
Considera sharding cuando un replica set optimizado no sostiene capacidad, localidad o volumen.
Una shard key debe evaluar:
cardinalidad;
frecuencia;
distribución;
monotonicidad;
targeting;
tenants outlier;
uniqueness;
cambios futuros.
Queries sin shard key pueden hacer scatter-gather. Sharding no corrige un mal schema o índice.
JavaScript
Copiar { _id : resourceId, businessId : session. businessId } El scope debe aplicarse en:
reads;
updates/deletes;
aggregations;
$lookup;
populate;
Search y Vector Search;
jobs y exports.
El businessId viene del contexto autenticado, no del body.
Roles de MongoDB protegen recursos del servidor; la aplicación protege reglas por usuario y tenant.
Nunca pases filtros, updates, sort, projection o pipelines completos desde una request.
TypeScript
Copiar const filter = {
businessId: auth. businessId,
status: input. status
} ; Valida runtime, limita $in, rangos, pagination y regex. TypeScript y casting del ODM no impiden operator injection.
MongoClient mantiene topology y pools. Reutilízalo por proceso.
pool checkout time;
wait queue;
server selection;
conexiones nuevas;
operation duration.
El pool permite concurrencia, no acelera una query individual. Calcula conexiones de todo el fleet y evita Promise.all() ilimitado.
input DTO;
modelo de dominio;
documento BSON;
hydrated document o lean result;
response DTO.
Una repository debe exponer operaciones con intención, no Filter<T> genérico.
Mongoose aporta ergonomía, pero no cambia las garantías del servidor ni protege writers externos.
compatible;
por batches;
reanudable;
idempotente;
observable;
limitada por carga;
validada;
con rollback o compensación.
Guarda checkpoints después de batches confirmados. Separa backfill de cleanup y conserva lectores compatibles hasta terminar.
Conecta síntomas con capas:
Texto
Copiar request lento
→ pool wait
→ query plan
→ working set/cache
→ disk
→ replication/topologíaMide percentiles, no solo promedios.
Observa conexiones, throughput, cache/eviction, disk, lag, oplog, scans, slow queries, backups y crecimiento.
Cada alerta necesita owner y runbook.
WiredTiger administra páginas, cache, compression, MVCC, history store, checkpoints y journal.
Transacciones largas retienen versiones; índices excesivos amplían working set; storage lento aumenta checkpoint pressure.
Diagnostica workload y métricas antes de cambiar parámetros internos.
journal: recuperación local tras crash;
oplog: replication y Change Streams;
audit log: acciones de seguridad;
outbox/eventos: intención de negocio;
backup: recuperación histórica.
Ninguno reemplaza a los otros.
Define RPO y RTO. Incluye datos, índices, validators, users/roles, GridFS, key vault/KMS y metadata de sharding.
Un restore test termina cuando la aplicación funciona y se validan invariantes, no cuando la herramienta deja de copiar archivos.
Después de recuperar, reconcilia sistemas externos y eventos posteriores.
Coordina servidor, FCV, drivers, Mongoose y herramientas.
Texto
Copiar driver compatible
→ backup/restore
→ staging
→ rolling binary upgrade
→ observación
→ FCV
→ nuevas featuresConservar FCV anterior preserva una ventana de evaluación. No actualices todos los componentes y actives nuevas capacidades en un solo cambio.
Text search, MongoDB Search y Vector Search resuelven problemas distintos.
Vector Search necesita embeddings, chunking, filters, versionado, evaluación y control de costes.
La búsqueda nunca reemplaza autorización ni debe ser source of truth para confirmar una escritura.
Define invariantes, escalabilidad, fallos, SLOs, partición y recuperación. MongoDB implementa una parte del sistema.
Gestiona validación, lifecycle del cliente, concurrencia, timeouts, cancellation, errors y DTOs.
Añade schemas, hydration, population y middleware. Debe permanecer como una capa explícita sobre el driver.
Ofrece un modelo relacional con constraints, joins y transacciones fuertes por defecto. No existe una base universalmente superior: compara access patterns, integridad, consultas y operación.
Hace reproducible el proceso, pero volumes, replica sets, secrets, backups y upgrades siguen siendo responsabilidades de operación.
Repositories, outbox, idempotencia y migrations conectan persistencia con casos de uso sin esconder las garantías reales.
Para una nueva funcionalidad:
escribe la invariantes;
lista access patterns;
estima cardinalidad y crecimiento;
elige límites documentales;
define tipos BSON y validation;
diseña operaciones atómicas;
decide si necesita transaction/outbox;
crea índices mínimos;
valida con explain;
añade tenant y seguridad;
define retries, timeouts e idempotencia;
prueba concurrencia y fallos;
diseña backup/migration;
instrumenta SLOs;
documenta trade-offs y owner.
Diseña un sistema de reservas de citas:
Texto
Copiar un usuario elige sede, servicio y horario
no debe existir doble reserva
el pago puede fallar
la cita puede cancelarse
se envían recordatorios
documento de disponibilidad;
unique/partial index para el slot;
idempotency key;
transaction entre cita y reserva;
outbox para pago/notificación;
expiración mediante job;
índices de agenda;
tenant/branch scope;
restore y reconciliación con pagos.
No empieces por elegir collections; empieza por las invariantes.
¿Qué representa cada documento?
¿Quién lo posee?
¿Qué campos son snapshots?
¿Qué arrays tienen máximo?
¿Qué tipos BSON se usan?
¿Qué campos pueden faltar o ser null?
¿Qué validator existe?
¿Cómo evoluciona el schema?
¿Qué PII contiene y cuánto se retiene?
filtro y tenant;
sort estable;
projection;
limit;
collation;
índice candidato;
explain;
valores outlier;
timeout;
autorización;
coste bajo concurrencia.
invariantes;
atomicidad documental;
precondition;
versioning;
unique indexes;
idempotency key;
transaction necesaria;
efectos externos;
write concern;
retry y resultado ambiguo;
audit/reconciliation.
topología y versiones soportadas;
red privada, TLS y users mínimos;
pool y timeouts;
índices y validators;
backups y restore tests;
SLOs, dashboards y alertas;
capacity y costes;
migrations y rollbacks;
failover/load tests;
runbooks y owners;
privacidad y retención;
upgrade path.
arrays sin límite;
documents cercanos a 16 MiB;
population o $lookup en cada request;
deep skip;
scans frecuentes;
índices sin owner;
hot documents;
transacciones largas;
migrations irrepetibles;
retries que duplican efectos;
tenant filters dispersos;
backups nunca restaurados;
alertas sin runbook.
MongoDB no se domina memorizando comandos. Se domina conectando dominio, documentos, queries, índices, concurrencia, topología y operación. Una decisión correcta hace explícitos sus límites, protege invariantes bajo concurrencia, se verifica con evidencia y tiene una estrategia para evolucionar y recuperarse.
Comprueba lo aprendido
¿Por qué el diseño comienza en las invariantes y no en las colecciones?
¿Qué criterios determinan embedding frente a reference?
¿Cuándo necesitas una transacción y cuándo basta un update condicional?
¿Cómo conectas query shape, índice y explain?
¿Qué capas protegen un sistema multi-tenant?
¿Qué diferencia existe entre replication, journal, outbox y backup?
¿Qué debe ocurrir antes de cambiar FCV?
¿Cómo comprobarías que un diseño está listo para producción?
Usa esta nota como mapa de navegación. Ante una decisión nueva, vuelve al proceso: requisito → invariantes → access patterns → documento → operación → índice → consistencia → seguridad → operación. Si puedes explicar y verificar cada paso, el diseño es defendible.