Naming, Shape Consistency, and Operational Conventions
Make documents predictable for every writer
A good schema is not only a relationship diagram. It also establishes consistent naming, types, timestamps, identifiers, and lifecycle conventions.
Naming conventions
Pick a consistent style for:
- collection names,
- field names,
- identifiers and reference fields,
- timestamps,
- status values,
- nested objects,
- enum-like values.
For example, use createdAt and updatedAt consistently instead of mixing created_at, createDate, and updatedOn across collections. Consistency improves query readability, validation, logging, and tooling.
Stable identifiers
Use _id for the document identifier. References should use a consistent type. If customerId is an ObjectId in one document and a string in another, equality queries and joins may not behave as expected.
If external clients need a public identifier, you can retain an internal _id and a separate stable public key. Do not expose secrets or authorization decisions merely because an identifier is hard to guess.
Timestamps
Common conventions:
createdAt: when the record was created.updatedAt: when the record was last changed.- Domain timestamps such as
publishedAt,paidAt,cancelledAt, oroccurredAtfor business events.
Use BSON Date consistently. Define whether timestamps represent event time, ingestion time, or last modification time; those are not interchangeable.
Status values
Use a controlled vocabulary such as pending, confirmed, failed, and cancelled. Define allowed transitions rather than allowing arbitrary strings. Schema validation can restrict values, while application logic or a state-machine layer enforces transition rules.
Keep document shapes coherent
Optional fields are normal, but inconsistent types are costly. If metadata is an object in most records and a string in a few, every consumer must handle unexpected shapes. Use validation and migrations to keep type drift under control.
Security-sensitive fields
Do not embed credentials, API secrets, or unnecessary sensitive data in broad-read documents. Separate data with different access controls where doing so simplifies authorization. Apply least-privilege database roles and field-level access practices appropriate to the application.
- createdAt:
Creation timestamp. - updatedAt:
Last modification timestamp. - Domain timestamp:
A timestamp tied to a business event, such as paidAt or publishedAt.
Consistent field names and BSON types reduce application branching and make validation, indexing, migrations, and debugging more reliable.
{
_id: ObjectId("65a000000000000000000090"),
customerId: ObjectId("65a000000000000000000010"),
status: "confirmed",
createdAt: ISODate("2026-05-10T10:00:00Z"),
updatedAt: ISODate("2026-05-10T10:05:00Z"),
paidAt: ISODate("2026-05-10T10:04:00Z"),
metadata: {
source: "web"
}
}- Standardize naming, identifier types, timestamps, and status values.
- Distinguish event time from record creation and update time.
- Keep sensitive fields out of documents that broadly accessible code can read.
Why should `customerId` use a consistent BSON type across documents?