PostHog Workflows vs Hogsend
What Hogsend is — a code-first lifecycle engine — why it makes PostHog dramatically better for teams that live in code, and how it splits from PostHog's own no-code messaging product.
Hogsend is a code-first lifecycle & marketing-automation engine. You write your onboarding emails, drip campaigns, and Discord/Telegram nudges as TypeScript journeys that live in your repo, run on your own infrastructure, and are triggered by the same PostHog events you're already capturing. It's what makes PostHog dramatically better for growth teams that live in code: the measurement stays in PostHog, and Hogsend turns those measurements into action you can version, code-review, and trust.
PostHog has its own messaging product (PostHog Workflows, formerly the open-source Laudspeaker). It's a no-code canvas for marketers, and it's good at what it does: batch sends and simple drip campaigns targeted on PostHog data.

This course pairs PostHog with Hogsend instead, for the lifecycle layer, because the audience here is people who build, and because the messaging layer is where the "owned by the people who build" principle actually bites. The split is deliberate:
| PostHog Workflows | Hogsend | |
|---|---|---|
| Authoring | Visual no-code canvas | Code-first TypeScript (defineJourney) |
| Lives in | PostHog cloud | Your repo, your infra, your email provider |
| Best at | Batch + simple drips, by marketers | Durable multi-step journeys, by developers |
| Versioned | A config in a UI | A dependency you pin and code-review |
| Logic | What the canvas exposes | Anything you can express in code |
The clean division of labour, which the rest of the course follows:
- PostHog detects — event collection, identity, cohorts, the analytics you read.
- Hogsend acts — the journeys that send the emails and Discord/Telegram messages, triggered by events, with the results fired back as events PostHog can measure.
To make "code-first" concrete before the lifecycle chapter builds it properly — this is a real journey shape, abbreviated:
defineJourney({
meta: { id: "activation-nudge", trigger: { event: "user.signed_up" } },
run: async (user, ctx) => {
await sendEmail({ to: user, template: "welcome" });
const { timedOut } = await ctx.waitForEvent({
event: "project.created",
timeout: hours(48),
});
if (timedOut) await sendEmail({ to: user, template: "activation-nudge" });
},
});Read what that buys you: the branching is ordinary TypeScript (if), the "wait up to
48 hours for the activation event" is one line, and the whole thing lives in a pull
request a colleague reviews. Now picture maintaining the same logic as boxes on a
canvas — then picture the version with three more branches. That divergence is the
whole argument, and it compounds with every condition you add.
You don't have to choose one forever. The point is that the measurement lives in PostHog and the code-first lifecycle automation lives in Hogsend — and the lifecycle chapters are entirely about why a code-first journey beats a flowchart once your logic gets real (behavioural branching, exact-once sends, holdouts you can prove).
Events, persons, and why it isn't GA4
Everything in PostHog hangs off events (a thing that happened) attached to a person (who it happened to). Get those two right and every chart works — and it's the exact place product analytics parts ways with GA4.
US cloud or EU cloud
PostHog Cloud runs in two independent regions, and you pick one at signup. Data does not move between them and you cannot merge across them — the one decision in this chapter that's hard to undo.