Marketing System
Summary
Marketing in LKCI is not a campaign sender. It is an operational state machine for deciding who may be contacted, why they are eligible, what message should be rendered, which human checks are required, which provider-bound actions are safe, and how later responses are interpreted. That distinction is the main reason the module is larger than a normal marketing automation integration.
The console is the best way to read the system. An operator starts with a business question: "Who should we reach, what should we say, and how will we know whether it worked?" The platform answers by splitting marketing into authoring, audience selection, geo handoff, suppression, run execution, review, delivery, actions, attribution, and analytics publication. Each piece has its own state because each piece fails differently.
Geo is a sibling module, not a marketing subfolder. Geo discovers and scores places; marketing decides campaign eligibility and runtime policy. The durable handoff is a saved geo selection imported into an audience draft, not a raw map query copied into campaign logic.
Module At A Glance
- Primary surface: campaign console, Audience Studio, Flow Studio, Template Studio, run detail, review queues, suppression setup, and insights.
- Main state machine: Marketing System State Machine.
- Core runtime shape: campaign authoring state becomes run-owned member, step, asset, delivery, event, and action state.
- Adjacent module: Geo Prospecting System, connected through saved selections.
The Operator Path
A useful marketing workflow starts before any message is sent. The operator needs to author campaign intent, select or build an audience, decide which template and flow apply, validate suppression, preview the run, review generated artifacts, and inspect outcomes later. If the console cannot explain one of those steps, the backend model is probably missing state.
This is why authoring state and runtime state are separate. A campaign, flow, template, trigger, action definition, and audience definition are editable intent. A campaign run, member, member step, rendered asset, delivery, event, and action execution are historical work. Normal authoring edits should affect future runs, not rewrite the behavior of a run that already started. That single rule protects most of the module's complexity from turning into surprising behavior.
The module's state-machine diagram should be read as the operator's checklist: intent, eligibility, permission, execution, review, side effect, measurement, repair. It is not just backend ceremony. Each state gives a person or job a specific place to stand when something is missing, blocked, stale, rejected, or ready to proceed.
Audience And Geo Handoff
Audience building is the point where marketing becomes accountable for eligibility. Source rows may come from SQL-backed audience definitions, customer or prospect facts, event triggers, or imported geo selections. They all have to become a common candidate contract before suppression, exposure, variant assignment, member creation, and entry-step work can proceed.
The geo handoff is intentionally narrow. Geo owns parcel evidence, H3 cells, drive-time features, score families, and saved selections. Marketing stores an audience definition that references the saved selection and then materializes members through the same marketing runtime path used by other audience sources. Geo does not create campaign members, apply suppression, reserve exposure, or decide delivery policy.
That boundary gives both modules room to improve. Geo can tune scores, expand coverage, or add market-insight layers without rewriting campaign runtime. Marketing can change suppression, templates, review gates, or attribution without learning how drive-time matrices are built. The link between them is product-level intent: a reviewed spatial selection that can become campaign eligibility.
Runtime Work
Runtime work is explicit before jobs process it. A run start resolves the flow, materializes members, creates member-step rows, snapshots action plans, and queues render work for a specific run_id + flow_step_id. Render jobs do not guess which campaign step is next. Action execution reads run action plans, not live authoring definitions. Even a zero-action step gets a snapshot so the system can prove that no actions were planned.
That sounds heavy until a real campaign is halfway through execution. A member may be suppressed, missing required template fields, blocked on identity resolution, awaiting review, approved for print, exported for distribution, or eligible for a post-send action. Those are different conditions with different repairs. Durable runtime state lets the console show the difference instead of collapsing everything into "failed" or "sent."
Provider-bound actions follow the same posture. Applying tags, creating notes, creating tasks, establishing customer targets, sending messages, or exporting distribution lists should happen through typed runtime plans, dispatch intents, idempotency keys, provider gateways, and result records. Page handlers should not perform those writes inline simply because the operator clicked a button.
Review, Delivery, And Repair
Human review is not a pause inside a job. It is OLTP-backed workflow state. Rendered assets can be revised, approved, rejected, published, and connected to delivery rows. Run-level artifacts such as mailing labels or distribution exports carry their own evidence. Delivery attempts and provider outcomes give support a way to distinguish a rendering problem from a review hold, a suppression change, an export issue, or a provider rejection.
The repair model matters because marketing side effects are visible outside the platform. A bad audience, missing suppression rule, wrong template field, or unsafe customer-target match can produce real customer contact. The system therefore favors reviewable state over clever automation. Automation should advance ordinary work quickly; uncertainty should become a queue, diagnostic, blocked action, or review task.
Attribution And Learning
Measurement is part of the system, not an afterthought. Runtime events, deliveries, exposures, source events, response attribution, experiment facts, lifecycle facts, and serving snapshots close the loop between a campaign's intent and its observed outcome. Without that loop, the platform would know that it sent something but not whether the audience, message, timing, or channel was useful.
The data boundary is important here. Marketing OLTP state records authoring, run execution, review, deliveries, actions, and events. Analytics jobs publish facts and compact serving snapshots for insight surfaces. UI/API code should not reconstruct campaign performance from raw analytics joins. It should read domain-owned projections and link back to run evidence when an operator needs to diagnose a result.
Visual
The system atlas is the primary visual for this post. It is intentionally dense: 82 nodes and 81 transitions across UI, API, authoring services, runtime services, review, jobs, OLTP state, analytics, providers, and guardrails. Open the full-size SVG to see how run-owned state, review, delivery, action dispatch, and attribution connect.
The state-machine diagram is the compressed lifecycle view. Read it from left to right: authoring creates editable intent; audience and suppression convert intent into permissible membership; runtime creates run-owned work; review and delivery decide whether artifacts can leave the platform; actions and attribution record consequences; repair paths keep ambiguous or failed states visible.
Reading Path
Start with this post for the operating model, then read Marketing Campaign Authoring for editable intent and Marketing Audience Building for eligibility. Use Geo Prospecting System and Geo Marketing Audience Handoff when the audience starts from spatial analysis. Use Marketing Run Execution, Marketing Review And Repair, and Marketing Insights And Quality after the lifecycle model is clear.
Why The Weight Is Worth It
The module's weight is justified only because marketing creates externally visible consequences. A campaign script can look efficient until it contacts the wrong identity, loses the reason a prospect was eligible, changes behavior mid-run after an authoring edit, or cannot explain whether a later booking should be attributed to the campaign. The platform version pays the cost upfront: snapshots, exposures, review states, action plans, delivery attempts, and analytics publication.
The payoff is operational leverage. Once eligibility, rendering, delivery, actions, and attribution are modeled as state, the console can show the exact reason work is blocked or complete. Jobs can retry specific steps. Tests can protect invariants such as run-owned action plans and explicit flow-step rendering. Future campaigns can reuse the same machinery instead of building a new sender path for each outreach idea.
Implementation Boundaries
app/web/app/marketing and app/api/marketing are operator and route surfaces. services/marketing/authoring owns editable campaign definition. services/marketing/runtime owns run start, materialization, rendering, delivery, actions, scheduling, and flow advancement. services/marketing/review owns human review operations. services/marketing/analytics owns publication and measurement. libs/marketing holds shared contracts. jobs/marketing contains thin entrypoints around service behavior.
The invariant is simple: durable work should exist as domain state before a job processes it, and provider side effects should be explainable after they happen.
Source Evidence
docs/domains/marketing.mddocs/domains/geo.mdapp/web/app/marketingapp/api/marketingservices/marketinglibs/marketingjobs/marketingpipelines/marketingtests/marketing