They asked for campaigns. First I had to decide who owned the user.
Realworld asked for five Customer.io lifecycle campaigns and a 70,000+ subscriber audience structured inside Beehiiv. I audited the infrastructure first, stopped the build, drew the ownership boundary between the two systems, cleaned the contact base, and then built six campaigns — the sixth because the audit found an onboarding gap.

The campaigns weren’t the problem. One audience sat across two systems, and nobody had decided which system owned which relationship.
Three different populations across two platforms. None is derived from another.
“The brief was five lifecycle campaigns and a 70K+ audience structured inside Beehiiv, quickly. I audited the infrastructure first — and stopped the build, because shipping onto that foundation would have produced numbers nobody could trust.”
Realworld helps adults navigate the moments nobody teaches you — housing, taxes, jobs, insurance, financial setup. It’s backed by Bezos Expeditions and by executives from Instagram, Pinterest and Etsy.
The scope was straightforward: build five lifecycle campaigns in Customer.io, migrate and structure a 70,000+ subscriber audience inside Beehiiv, and move fast.
Before building anything, I audited the infrastructure underneath the brief.
Four things the brief didn’t account for.
Gmail and Outlook were flagging sends as spam, and the sending infrastructure hadn’t been designed for long-term deliverability.
The existing lifecycle campaigns had no clear segmentation logic — no definition of who should receive what, or when someone should stop receiving it.
The Customer.io database carried unsubscribed contacts, anonymous and fake IDs, and records with no email address at all — none of them separated from the audience the campaigns would enter.
Two systems were about to address one audience, with no rule saying which of them owned which relationship.
Building five campaigns on that foundation would have produced misleading results and poor inbox placement — and the post-mortem would have blamed the copy and the strategy, because those are the visible variables. The real cause would never have surfaced.
Project source
So I stopped the build.
That was the harder conversation and the more valuable one. The audit wasn’t a formality before the real work — it changed what the real work was.
Who owns the user?
The brief treated Customer.io and Beehiiv as two tools to set up. They’re two owners of the same audience, and the useful question isn’t which is better — it’s which one owns which part of the relationship.
Diagram: two systems either side of one boundary. Customer.io owns active product users and runs onboarding, activation, nurture, win-back and re-engagement. Beehiiv owns dormant reactivation through a phased warmup that prioritises the most-engaged cohorts. Neither system emails the same user at the same time, and a Beehiiv subscriber who converts permanently exits into the Customer.io flows.
A Beehiiv subscriber who converts permanently exits the Beehiiv journey and enters the Customer.io lifecycle flows.
That single rule decided the eligibility logic underneath everything else: who could enter a campaign, who was suppressed, and which system a given person belonged to at any moment.
Defining the audience before the campaigns.
The audience the campaigns would actually reach had to be defined before the campaigns existed.
I also created an invalid-email segment so contacts with no email address could never enter a campaign in the first place. The four remaining cohorts became the basis for the phased Beehiiv warmup — you can’t prioritise the most-engaged audience until you can name it.
Before a single campaign was built, I wrote the lifecycle strategy document and had it reviewed and approved.
- Campaign objectives
- Trigger logic
- Audience definitions
- Behavioural conditions
- Exit criteria
- Deliverability rules
Deliverability standards were rebuilt into the campaign templates themselves: clean HTML structure, plain-text compatibility, lightweight formatting, proper unsubscribe handling, and a single-CTA email architecture.
Five became six.
The brief called for five campaigns. The audit surfaced an onboarding gap, so the final build expanded to six.
The additional sequence existed to improve new-member activation and lifecycle continuity — a gap that only became visible once the audience was segmented and the ownership boundary was drawn. The campaign types the build covered: onboarding, activation, re-engagement, win-back and nurture.
Project sourceThe project record names five campaign types across six campaigns, so the sixth isn’t enumerated here.
The result is the architecture.
The Beehiiv warmup was designed — the project record doesn’t establish that it ran. What follows the initial build is operating work, and it is labelled as such.
- An ownership boundary between Customer.io and Beehiiv, with the suppression and eligibility logic that enforces it
- A 78,708-contact database reviewed and restructured, with 11,032 exclusions and removals
- An invalid-email segment blocking no-email contacts from entering any campaign
- Four defined audience cohorts: Founding Cohort, Inactive, Pre-Trial, Blank Status
- A lifecycle strategy document — objectives, triggers, audiences, conditions, exit criteria, deliverability rules — reviewed and approved before implementation
- Six behaviour-driven Customer.io campaigns, one more than briefed
- Deliverability standards rebuilt into the campaign templates
- A designed phased Beehiiv warmup prioritising the most-engaged cohorts
Three things the system was already telling us.
The initial build was the brief. What came after was reading the system it now sat inside.
- 01The product emitted more than the lifecycle used
Customer.io held 85 product events. Thirteen were in use by lifecycle automation. Reading the index row by row, the events wired into automation clustered around account creation and onboarding; higher-stage product events such as Login, LessonCompleted and TaskCompleted carried no automation usage at all.

ScreenshotCustomer.io, Data index → Events. The account’s own filters: All events (85), Events in use (13). The Usage column records which automations reference each event. Open full size - 02Widening the audience rule changed the outcome
Two sends of the same newsletter, a week apart, used different audience rules — different segment conditions and different subscription targeting. The behaviourally constrained send: 189 emails sent, 0.0% failed. The send to everyone subscribed to email: 5,294 emails sent, 36.9% failed — 3,094 of them.
Calculated5,294 sent + 3,094 failed = 8,388 attempted. 3,094 ÷ 8,388 = 36.9% — the rate Customer.io reports against Failed.

ScreenshotCustomer.io, Sunday Reset — each send’s Recipients rule with its own all-time metrics directly beneath it. Above (30 August): people in Web Users and Activated Users, subscribed to the sunday reset topic — 189 sent, 0.0% / 0 failed. Below (6 September): everyone subscribed to email — 5,294 sent, 36.9% / 3,094 failed. Failed is a separate column from Bounced and Suppressed. Open full size - 03The sender requirements were not the gap
Against Gmail’s sender requirements, every authentication and configuration requirement read Compliant — SPF and DKIM, From: header alignment, DMARC, encryption, DNS records, one-click unsubscribe, honour unsubscribe. The one requirement marked “Needs work” was user-reported spam rate, and that one row is why the dashboard reports the domain as not meeting sender requirements.

ScreenshotGoogle Postmaster Tools, Compliance status, realworld.co — last updated 10 September 2026. Seven requirements Compliant; user-reported spam rate marked Needs work against a 0.3% threshold, which is what trips the “You don’t meet our sender requirements” notice below it. Open full size
A send went out. Then it was taken apart.
A re-engagement email went out in June. The work afterwards was reading what it did.
The audience was split by what each person did with that send: never opened, opened but didn’t click, clicked. Written into the segment itself, against the group who never opened: likely a subject-line problem, not content.
The 103-person clicked cohort was identified in Beehiiv as the “warmest segment for targeted follow-up.” Beehiiv’s All subscribers list held 65,332 records at inspection.

The part that didn’t get built.
None of this was executed inside the engagement. It is what the audit pointed at.
No metric existed for what makes a Realworld user activated — so nothing downstream could be measured against it.
Analyse the cohort already sent to, segment the remainder by lifecycle status, roll out under suppression rules, then route by what each person did.
Monitor → analyse → prioritise → build or fix → measure → iterate, run weekly rather than campaign by campaign.
Project sourceDesigned and documented. Not executed inside the engagement.
“Isaac was prompt, professional, and thoughtful. I would absolutely work with him again.”
Six days later, Realworld hired me again.
Account-confirmed
Sometimes the highest-value work isn’t executing the brief. It’s identifying the problem underneath it — before the build makes it invisible.