Convex App
Database Triggers
Automatic side effects on database changes using convex-helpers triggers.
YeetCode uses the convex-helpers trigger system to run side effects when database records change. This lets you react to inserts, updates, and deletes without scattering event-handling logic across every mutation.
How It Works
Instead of using Convex's built-in mutation and internalMutation directly, we wrap them with trigger-aware versions that intercept database operations and fire registered callbacks.
Setup
The trigger system is configured in apps/convex/triggers.ts:
import { mutation as rawMutation, internalMutation as rawInternalMutation } from "./_generated/server";
import { Triggers } from "convex-helpers/server/triggers";
import { customCtx, customMutation } from "convex-helpers/server/customFunctions";
import type { DataModel } from "./_generated/dataModel";
const triggers = new Triggers<DataModel>();
// Register triggers for specific tables
triggers.register("users", async (ctx, change) => {
if (change.operation === "insert") {
console.log("user created in db event triggered.");
}
});
// Export wrapped mutation functions
export const mutation = customMutation(rawMutation, customCtx(triggers.wrapDB));
export const internalMutation = customMutation(rawInternalMutation, customCtx(triggers.wrapDB));Using Trigger-Aware Mutations
Any mutation that should fire triggers must import mutation or internalMutation from triggers.ts instead of from _generated/server:
// ✅ Correct — triggers will fire
import { internalMutation } from "./triggers";
// ❌ Wrong — bypasses triggers
import { internalMutation } from "./_generated/server";Trigger Callback
The callback receives:
ctx— The Convex mutation contextchange— An object describing the operation (insert,update, ordelete) and the affected document
triggers.register("users", async (ctx, change) => {
if (change.operation === "insert") {
// New user created — send welcome email, log analytics, etc.
}
if (change.operation === "delete") {
// User deleted — clean up related data
}
});Current Triggers
| Table | Operation | Behavior |
|---|---|---|
users | insert | Logs user creation (placeholder for future logic like welcome emails) |
When to Use Triggers vs. Inline Logic
- Triggers are good for cross-cutting concerns (audit logging, analytics, cascading deletes) that should happen regardless of which mutation caused the change.
- Inline logic is better for business logic specific to a single mutation path.