Solo Founder Product Engineering Handbook
Event Taxonomy Template
Define a small set of product events whose proof boundaries, identities, failures, and decision uses remain trustworthy as the product changes.
Begin with the Decision the Events Must Change
An event taxonomy is not an inventory of things the interface can report. It is a compact account of what happened in the customer’s work, strong enough to challenge memory and small enough for one founder to inspect.
Write the next decision before naming an event:
Decision this evidence must change:
Customer and painful workflow:
Promised outcome:
Natural cadence of the workflow:
Activation means:
Strongest defensible evidence of value:
Evidence of repeated value:
Operational burden that could make success misleading:
Date or sample size at which we will decide:
Suppose a product helps an account manager turn an advertising export into a reviewed weekly digest and send it to a client. The founder needs to decide whether to improve import reliability, improve digest quality, or narrow the target agency segment. Signups and page views cannot answer that question. The taxonomy must show whether an intended agency entered the real workflow, received a usable digest, trusted it enough to send, returned at the weekly cadence, and needed founder help along the way.
Trace One Value-Producing Workflow
Draw the shortest path from arrival to repeated value using product facts rather than screens:
account created
-> source export accepted
-> digest generated
-> digest reviewed
-> delivery accepted
-> next eligible weekly delivery accepted
Add broken branches where they can change the decision:
source export rejected
digest generation failed
delivery failed
founder intervention required
This is the boundary of the day-one taxonomy. A click, open panel, or page view stays outside unless it answers a question that the workflow events cannot. A product with several important workflows should begin with the one whose success or failure would most change what the founder builds next.
Now give every step an owner in the product model. For the agency workflow, the durable identifiers are the agency account, acting user and role, client, source export, digest, and delivery. If the taxonomy cannot say which customer and value-carrying object an event concerns, the data model is not yet ready to support the claim.
Write the Proof Boundary Before the Name
Complete one event record at a time:
Event name:
Product fact represented:
Emitted when:
Authoritative emitter:
Actor:
Owning account:
Primary object and stable identifier:
Related object identifiers:
Occurred-at timestamp:
Result:
Required decision properties:
This event proves:
This event does not prove:
Founder decision or conversation it can trigger:
Sensitive data deliberately excluded:
Systems that receive the event:
Deduplication or idempotency rule:
Schema owner:
Definition version:
Retire, split, or rename when:
The proof boundary prevents a convenient signal from acquiring a grander meaning. digest_generated proves that software produced a candidate. It does not prove that the account manager trusted the output. digest_delivery_accepted is stronger than send_clicked, but provider acceptance still does not prove that the client read, understood, or valued the message.
Name the durable fact rather than the current interaction. source_export_accepted can survive a redesigned upload flow. clicked_import_button cannot. Use a consistent verb tense, reserve names before implementation, and never silently reuse an old name for a new meaning.
Complete One Contract All the Way Through
For the agency product, the delivery event could read:
Event name: digest_delivery_accepted
Product fact represented: a reviewed digest entered the client-delivery path
Emitted when: the delivery provider confirms acceptance
Authoritative emitter: the server process handling the provider result
Actor: account user who approved the send
Owning account: agency account
Primary object: delivery_id
Related objects: client_id, digest_id, approved_digest_version
Occurred-at timestamp: provider acceptance time, normalized to UTC
Result: accepted
Required decision properties: actor_role, target_segment, acquisition_source,
channel, digest_required_editing, founder_help_required
This event proves: an account manager trusted a particular digest enough to
send it and the provider accepted that delivery
This event does not prove: inbox placement, opening, comprehension, or client value
Decision use: compare agencies that stop after generation with those that send;
trigger a conversation when a reviewed digest is not sent
Sensitive data excluded: client name, recipient address, digest body, source data
Systems receiving the event: product event store and founder decision board
Deduplication rule: one accepted event per provider delivery identifier
Schema owner: founder
Definition version: 1
Retire, split, or rename when: a channel has a materially different proof boundary
The event payload can remain compact because the contract carries the semantics:
{
"event": "digest_delivery_accepted",
"event_version": 1,
"occurred_at": "2026-07-07T08:42:11Z",
"account_id": "agency_018",
"user_id": "user_204",
"actor_role": "account_manager",
"client_id": "client_073",
"digest_id": "digest_661",
"digest_version": 3,
"delivery_id": "delivery_992",
"target_segment": "small_marketing_agency",
"acquisition_source": "founder_outreach",
"channel": "email",
"digest_required_editing": true,
"founder_help_required": false,
"result": "accepted"
}
Identifiers and bounded categories make the event useful without copying the customer’s work into another system.
Assemble the Smallest Taxonomy That Can Disagree with You
Copy the event record for each consequential fact on the workflow trace. A first pass for the agency product might contain:
account_created, carrying acquisition source, intended segment, and creator role;source_export_acceptedandsource_export_rejected, separating entry into the real workflow from import failure;digest_generated, carrying the generation result without claiming customer value;digest_reviewed, showing whether a person inspected and edited the candidate;digest_delivery_acceptedanddigest_delivery_failed, preserving the provider outcome rather than a button press;founder_intervention_recorded, naming the blocked step, bounded reason, outcome, and time spent;subscription_started,subscription_renewed, andsubscription_cancelled, attached to the paying account;teammate_invitedorreferral_submittedonly if collaboration or spread can change the next decision.
The number is not a target. Remove any event that cannot change a decision, trigger a useful conversation, explain a failure, or protect the meaning of another event. Add an event when a consequential part of the product story remains invisible. Do not fill categories merely to make the list look complete.
Record failure beside the workflow it interrupts. A generic error_occurred event will not reveal whether an account rejected the value proposition or the product blocked the value moment. Keep exception text, tokens, files, prompts, and arbitrary customer input out of analytics. Link to restricted diagnostic systems with a safe correlation identifier when deeper investigation is necessary.
Founder intervention also belongs in the taxonomy. If the founder repairs an export, rewrites a digest, changes a record, or coaches the user through delivery, the workflow did not succeed unaided. Hidden labor can make activation and retention look healthy while the product becomes impossible for one person to operate.
Protect Identity and Meaning
Decide where value belongs before building a dashboard. A user can leave while their account adopts the product; one enthusiastic operator can also make a doomed account look healthy. Attach events to the account, actor and role, and value-carrying object when those distinctions are needed to reconstruct the customer story. Billing belongs to the paying account even when a user initiated checkout.
For every property, finish this sentence:
If this property changed, we would change ________.
Keep it when the answer names a product, onboarding, support, sales, pricing, trust, or operating decision. Remove it when the answer is curiosity. Prefer stable identifiers, controlled categories, statuses, counts, and duration bands over names, addresses, documents, free text, or customer content.
Record where the event data travels and how long each destination retains it. Mark test and founder accounts. Know how an excluded or deleted account is handled. If the founder cannot explain what customer behavior has been copied, where it went, and why it is needed, the taxonomy is not small enough.
Make Implementation Disagree Loudly
Keep one canonical taxonomy document or schema. Validate event names, versions, and required properties at the authoritative emitter. An event emitted from the browser may show an attempted action; a server, job, provider callback, or reconciled billing record should report the outcome it alone knows.
Define what happens when emission is retried. One customer action must not become several apparent successes. Decide whether occurred_at is the product fact’s time or the collector’s receipt time, and retain both only when late arrival matters. When meaning changes, version, split, or retire the event. Do not repair a dashboard by quietly redefining history.
For every event, write one acceptance example and one rejection example:
Emit digest_delivery_accepted when the provider accepts delivery_id delivery_992.
Do not emit it when the user presses Send, when the request times out, or when
the provider rejects the recipient.
Then test the complete trace against product records. Choose one account that reached value and one that stopped or failed. Confirm that the events preserve their order, owners, objects, retries, proof boundaries, and founder interventions. The trace should answer why the accounts diverged without requiring the founder to invent a story around missing data.
Finish with a Decision Query
Before implementation, write the first question the taxonomy must answer in ordinary language:
Among intended agency accounts that attempted an export this week, which reached an accepted client delivery, which stopped at review, which were blocked by a product failure, and which required founder help?
Specify the eligible accounts, time boundary, event sequence, strongest value proxy, failure branches, and intervention signal. If the event contracts cannot answer the question without treating absence as proof, revise them now.
The taxonomy is ready when another careful engineer could emit each event without guessing, a founder could inspect one customer’s path from product records to events, and every collected fact has a decision use and a defensible privacy cost. Preserve it beside the core object map and change it when the product’s promise or proof boundary changes—not whenever the interface acquires another button.
Continue reading
Full table of contents