Skip to main content
Version: 1.3.1

Hooks

Hooks let you run custom code around collection lifecycle events. They are ideal for enforcing invariants, populating derived fields, or triggering side-effects (metrics, queues, audit logs).

Supported hooks

HookSignatureRuns when
beforeInsert(doc)Mutable documentAfter schema validation, before persistence
afterInsert(doc)Immutable snapshotAfter the document is stored
beforeUpdate({ previous, next, update })Mutable nextBefore indexes update
afterUpdate({ previous, next })Immutable snapshotsAfter the document is stored
beforeDelete(doc)Immutable snapshotBefore the document is removed
afterDelete(doc)Immutable snapshotAfter removal

Hooks can be async and throw errors to abort the operation.

Example

const users = db.collection("users", {
hooks: {
beforeInsert(doc) {
doc.slug = doc.name.toLowerCase().replace(/\s+/g, "-");
doc.createdAt = new Date().toISOString();
},
afterInsert(doc) {
metrics.increment("users.created");
audit.log({ action: "create", collection: "users", id: doc._id });
},
beforeDelete(doc) {
if (doc.role === "owner") {
throw new Error("Cannot delete owners");
}
},
},
});

Composition

Calling db.collection("users", { hooks }) multiple times merges the handlers. This makes it easy to split hooks across modules (e.g. auditing vs. validation).

Tips

  • Keep hooks fast—heavy work should move to background jobs.
  • Always defensively clone external inputs (e.g. network payloads) before mutating them.
  • When combining with schemas, remember: schema → validator → beforeInsert/beforeUpdate.