{
    "slug": "db_triggers",
    "term": "Database Triggers",
    "category": "database",
    "difficulty": "intermediate",
    "short": "Stored procedures that fire automatically on INSERT, UPDATE, or DELETE — useful for audit logs and enforcing constraints, but dangerous when they become hidden business logic.",
    "long": "Triggers execute SQL logic automatically when data changes. Common legitimate uses: audit trails (log who changed what and when), denormalised counter updates (post_count on user table), enforcing complex constraints not expressible as check constraints, and maintaining summary tables. Dangers: invisible side effects (application writes one row, trigger writes five more), performance surprises (a simple INSERT triggers complex logic), testing difficulty (tests must set up trigger state), and debugging complexity (unexpected data changes have invisible causes).",
    "aliases": [
        "AFTER INSERT",
        "BEFORE UPDATE",
        "database trigger",
        "row-level trigger"
    ],
    "tags": [
        "database",
        "sql",
        "architecture"
    ],
    "misconception": "Triggers are good for keeping derived data in sync — the outbox pattern or application-level events are more transparent and testable; triggers hide logic that developers must know exists.",
    "why_it_matters": "Invisible trigger logic causes mysterious data changes — a developer deletes a row, three other rows change via trigger, and debugging takes hours because the trigger is not visible in application code.",
    "common_mistakes": [
        "Complex business logic in triggers — impossible to unit test and invisible to application developers.",
        "Triggers that call external services — synchronous triggers block the transaction; use the outbox pattern.",
        "Cascading triggers — trigger A fires trigger B which fires trigger C; debugging is nearly impossible.",
        "Not documenting that triggers exist — future developers modify the table unaware of side effects."
    ],
    "when_to_use": [],
    "avoid_when": [],
    "related": [
        "db_stored_procedures",
        "outbox_pattern",
        "ai_in_php",
        "event_sourcing"
    ],
    "prerequisites": [
        "db_stored_procedures",
        "acid_properties",
        "database_indexing"
    ],
    "refs": [
        "https://www.postgresql.org/docs/current/trigger-definition.html"
    ],
    "bad_code": "-- Trigger hiding business logic:\nCREATE TRIGGER after_order_insert\nAFTER INSERT ON orders FOR EACH ROW\nBEGIN\n    -- Sends email (makes HTTP call from trigger!)\n    -- Updates inventory across 3 tables\n    -- Calculates customer loyalty points\n    -- Updates denormalised reporting tables\nEND;\n-- Developer INSERT INTO orders... has no idea this fires",
    "good_code": "-- Trigger for legitimate audit only:\nCREATE TRIGGER audit_order_updates\nAFTER UPDATE ON orders FOR EACH ROW\nBEGIN\n    INSERT INTO order_audit_log\n        (order_id, old_status, new_status, changed_at, changed_by)\n    VALUES (OLD.id, OLD.status, NEW.status, NOW(), @current_user);\nEND;\n-- Business logic stays in PHP where it's testable and visible",
    "quick_fix": "Avoid triggers for business logic — they fire invisibly, making application behaviour hard to trace and test; use PHP application events instead for audit logging and side effects",
    "severity": "medium",
    "effort": "medium",
    "created": "2026-03-16",
    "updated": "2026-03-22",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/db_triggers",
        "html_url": "https://codeclaritylab.com/glossary/db_triggers",
        "json_url": "https://codeclaritylab.com/glossary/db_triggers.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[Database Triggers](https://codeclaritylab.com/glossary/db_triggers) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/db_triggers"
            }
        }
    }
}