Yellow Theme

Next start · November 2026

Notes / 22

2026-09-24

The CRM is not the funnel

We cut the product CRM over for people and deals. The weekly board still looked empty. Counters had never lived there.

Thesis: People and deals belong in the CRM. Weekly counters stay on the event store that recorded them. After a cutover, match the ACL to the CRM objects — do not expect the CRM to invent analytics it never stored.

What we shipped first

We moved contacts and opportunities into the product CRM. The weekly ops board still queried the CRM for “briefs this week.” The pipeline column went blank. The counter API on api.example.com still had the numbers. The board had pointed at the wrong persistence boundary.

The working shape

Keep people and deals on crm.example.com. Keep weekly counters on the event store. When the CRM becomes the source of truth for pipeline, grant the board ACL to those objects — and leave analytics where the events already landed.

// Persistence boundary: people/deals in CRM; weekly counters stay on the event store.
const crm = {
  host: "crm.example.com",
  people: [{ id: "p_1", name: "Alex", companyId: "c_9" }],
  opportunities: [{ id: "o_1", stage: "brief", personId: "p_1" }],
};

const eventStore = {
  host: "api.example.com",
  counters: { briefs_this_week: 4, fit_notes_sent: 2 },
};

// Board after CRM cutover — ACL must allow the CRM objects.
// Counters still read from the event store, not from CRM stages.
function boardSnapshot({ crmAclOk }) {
  return {
    pipeline: crmAclOk ? crm.opportunities : [],
    week: eventStore.counters,
  };
}

boardSnapshot({ crmAclOk: false }); // { pipeline: [], week: { … } }  — empty board
boardSnapshot({ crmAclOk: true });  // people/deals visible; counters unchanged

Checklist

Related: Reading Mode dropped the FAQ answers. How we deliver: methodology · readiness.

Engineering commentary only — not audit, legal, or certification advice.