MongoDB Data Modeler Associate common mistakes
MongoDB Data Modeler Associate · Understand the traps and how to avoid them.
Embedding an unbounded array (e.g., every order line, log entry, or comment) inside a single parent document without considering the 16 MB BSON document limit or how the array grows over time.
Candidates optimize for the read pattern ('one query gets everything') and treat embedding as always correct, forgetting that arrays that grow without a hard cap eventually hit the document size limit and force awkward splitting later.
What to do instead
Apply the bounded-array rule: embed only when the array has a natural, small upper bound (e.g., a shipping address, a handful of tags). For unbounded child sets, use the subset pattern (embed the most recent N, reference the rest) or the outlier pattern, and state the assumed bound in the model.
Choosing references over embedding (or vice versa) based solely on which is 'normalized' or 'cleaner', without listing the concrete queries the application will run.
Candidates carry relational instincts from prior experience and treat normalization as a virtue, so they model entities independently before enumerating access patterns.
What to do instead
Before finalizing the model, write out the top 5-10 queries with their expected frequency and result shape. Embed when the data is accessed together and belongs to one entity; reference when the child is large, shared, or independently queried. Justify each choice against a named access pattern.
Assuming that referencing a child document by its _id is automatically 'safe' because MongoDB enforces referential integrity, and never planning for orphaned references.
The relational mental model assumes foreign-key enforcement; MongoDB has no such constraint, and candidates miss that deletes and updates must be handled in application logic or with $lookup.
What to do instead
Explicitly state the referential-integrity strategy: application-level cascade on delete, a background consistency job, or acceptance of orphans. Remember that $lookup resolves references at read time but does not enforce them.
Modeling a many-to-many relationship by embedding the full list of _ids on both sides, producing two arrays that must be kept in sync on every insert or delete.
Candidates see two-way references as symmetric and convenient for querying from either direction, but they overlook the doubled write cost and the risk of divergence between the two arrays.
What to do instead
Store the relationship on one side only, or introduce a junction collection when the relationship carries its own attributes (role, join date, status). Duplicate the other side only if a measured read pattern requires it, and document the write path that maintains both.
Treating the schema as fully flexible and never adding schema validation, so the collection accumulates documents with inconsistent field names, types, and casing.
'Schemaless' is misread as 'no schema needed'; candidates skip the design step and assume the application will always write well-formed documents.
What to do instead
Define an intentional schema and enforce it with JSON Schema validators ($jsonSchema) at the collection level, using the validationLevel and validationAction settings appropriate to rollout. Document optional fields and their types in the model description.
Applying the extended reference pattern (copying fields from a parent into a child) without planning how the duplicated fields are updated when the source changes.
Candidates learn that duplication avoids $lookup and improves read performance, but they do not consider the write amplification and staleness that duplication introduces.
What to do instead
For every duplicated field, name the fields that are copied, the trigger that refreshes them (e.g., an update hook on the source, a periodic job), and the acceptable staleness window. Only duplicate fields that are small, rarely change, and are needed on the hot read path.
Designing a bucket or time-series pattern without choosing a bucketing key and granularity tied to the query range, resulting in buckets that are too large or too granular.
Candidates know the pattern name but not the sizing math; they pick an arbitrary bucket size and do not check it against the document limit or the typical time range queried.
What to do instead
Compute the bucket size from the write rate and the expected query window (e.g., one bucket per device per day), verify the worst-case document size stays well under 16 MB, and include a count or metadata field so aggregation can skip empty or partial buckets.
Creating one index per field used anywhere in a query, ignoring compound-index order and the ESR (Equality, Sort, Range) rule.
Candidates index reactively field by field and do not reason about how the query planner uses prefix ordering; they assume more indexes always means better performance.
What to do instead
Design compound indexes by listing the query's equality predicates first, then the sort fields, then range predicates. Verify with explain() that the index is used (IXSCAN, not COLLSCAN) and that no in-memory SORT stage appears, and drop indexes that are redundant prefixes of others.
Forgetting that a multikey index on an array field has one index entry per array element, and expecting the same selectivity and write cost as a scalar index.
Candidates treat array fields like scalar fields when estimating index size and performance, missing the multiplied key count and the restriction that a compound index cannot have two array fields.
What to do instead
Account for multikey cardinality when sizing indexes and planning memory. Avoid compound indexes with more than one array field, and consider the subset pattern to keep indexed arrays small. Confirm multikey behavior with explain().
Ignoring the document's field order, nesting depth, and field-name length when estimating storage and working-set size, then being surprised by poor cache behavior.
Candidates estimate size from the logical data volume only, forgetting that BSON stores field names in every document and that long, deeply nested names inflate the working set.
What to do instead
Estimate document size from actual BSON (bsonSize or a sample insert), shorten frequently repeated field names where justified, flatten unnecessary nesting, and compare total collection size against available RAM to reason about the working set.