May 14, 2026

Inside Flows — three triggers, four steps, and why that's enough

Inside Flows

The automation industry taught you to judge a tool by the size of its catalog. "Five thousand integrations." "Connects with everything." The number is large on purpose, because the number is the pitch.

LaunchWithAgency's Flows product is built on the opposite suspicion: that a huge connector catalog is the symptom of a problem, not its solution. You only need five thousand connectors if your data is scattered across five thousand islands. When it sits in one database, automation gets small — and the smallness is the feature. This article opens up Flows: three triggers, four steps, and the case for why stopping there is a decision, not a shortfall.

The model: trigger → run → steps

A flow (flows) has a minimal, complete structure. It has a trigger, which defines when it runs. It has a sequence of steps (stored as a single JSON blob, stepsJson), which defines what it does. And every time it fires, a run is born (flow_runs), recording what actually happened.

Notice that the steps live in a single JSON field on the flow's own row. There is no elaborate steps table with complex relationships — there is an ordered array of step descriptors, serialized. That is the same leanness philosophy that runs through the whole suite: the structure is as simple as it can be without ceasing to be complete.

The three triggers

A flow fires in one of three ways, and the third is the one that truly matters.

Webhook. The flow exposes a public URL; calling that URL starts a run. It is the bridge to the world outside the suite — a checkout, an external form, an internal system you still keep.

Schedule. The triggerKind is schedule, and the config states the cadence: every minute, hour, day or week. It is time-based automation — a weekly digest, a daily cleanup.

Internal event. The triggerKind is event, and the config names an event — for example newsletter.subscribed. Here is the heart of Flows. When something happens inside the suite, the responsible product records an event in the flow_events table, in the same database. And, in the same instant, the system matches that event against the flows listening for it. There is no webhook traveling across the internet, no third-party queue — the event and the flow live in the same file. (This is developed in the article "The end of Zapier.")

The four steps

Once fired, the flow runs its steps in order. There are four kinds, and LaunchWithAgency's bet is that those four cover 95% of real marketing automation.

Email. Sends an email — the welcome, the nurture, the notice. Because Flows and Emails share the database, this step needs no third-party credential: it uses the suite's own sending infrastructure.

HTTP. Makes an HTTP call outward. It is the escape step: when you need to notify an external system, this is the way.

Delay. Waits. One day, three days, a week. It is what turns an immediate reaction into a sequence: "when the lead comes in, wait two days, then send."

If. Evaluates a condition and branches. It is what gives the flow intelligence: "if the subscriber opened the first email, send the second; if not, send a reminder."

Email to act, HTTP to talk to the outside, Delay to wait, If to decide. Combine the four and you write "when someone subscribes to the newsletter, wait a day, send the welcome; three days later, if they didn't open it, send it again with a different subject." That is the shape of almost every marketing automation that exists. The fifth, sixth, hundredth step kind would serve the remaining 5% — and would cost the simplicity that serves the 95%.

> A catalog of five hundred connectors isn't generosity. It is the confession that the data is trapped in five hundred places. Flows has four steps because the data is in one place.

The run: automation that leaves a trail

Every time a flow fires, a row is born in flow_runs. It holds the triggerPayloadJson — what started the run —, the status (running, succeeded, failed), the start and end times, and the decisive field: stepLogsJson.

That last one is a step-by-step log. For each step, it records the status, the output produced, the error if any, and the timestamps. When an automation fails — and automations fail —, you are not facing a black box. You open the run and see exactly which step broke, what it received, and what it tried to do. The automation isn't only executed; it is auditable.

That is a huge practical difference from glue-automation. When a Zap fails, you often find out late and investigate in the dark. When a flow fails, the entire history is a row in the same database as everything else — inspectable with a SQL query.

The smallness is the proposition

Flows deliberately refuses the giant-catalog path. Three triggers, four steps, auditable runs, all in the same database as the other four products. The project's README calls it "the minimal Zapier that fits in the same database" — and the key word is minimal, said with pride.

Because the automation you need isn't the largest possible. It is the one you understand in full, that reacts without latency to your own operation's events, that has no third-party integration to break, and that leaves a legible trail when something goes wrong. Flows is small because the operation it automates doesn't need it to be big — it needs it to be reliable.