Should I vibe code
An AI lifecycle marketer that proposes, writes, sends, and keeps rewriting a SaaS product's welcome, activation, and churn-save emails
Nobody read that email before it went out. Not you, and not the model that wrote it.
?
Their verdict, the Starter price and the build-time estimate come from their entry, MIT-licensed. Checked 2026-08-04.
?
Our verdict, the regret score and everything below it. Editorial and unsponsored — nobody can pay to be moved.
The honest answer
why the verdict is what it is
Mara is lifecycle email with the copywriter removed as well as the sender. The build is not exotic — Stripe webhooks in, a small events API, a state machine per user, a model to draft, a provider to deliver — and an agent will get you a working version faster than you can read this page. What you own afterwards is a program that decides on its own when somebody who signed up for your product hears from you, and writes what they hear over your name. Two things make that worse than the usual automation argument. The trigger feed comes from your own database, so every backfill, replay and staging misconfiguration is now a send. And the words are generated, which means "we reviewed the copy" is a statement about a template rather than about the message that actually left with a customer's name on it. What keeps this out of the red band is that the recipients are your own signed-up users, which is the best consent story email has. Point the same machinery at a list you bought and read the Mailchimp page instead.
What actually breaks
not "if". the specific failures.
- The event feed, the first time somebody backfills a table and every user who ever signed up is freshly "created" within the hour
- Staging pointed at the production sending key, which is not a rare mistake — it is the default one
- The events endpoint, if it takes a user id and an email address without authentication. That is an open relay for welcome mail on your own domain, addressed to anyone
- Idempotency, or its absence: a worker that retries after a timeout sends the second copy to somebody who already read the first
- Personalisation, which is a model confidently writing "I saw you set up your third project last Tuesday" about something that never happened
- The approval queue, which is the entire safety mechanism, and which everybody switches off in week three because reading forty drafts a day is a job
- Reply handling, the moment a drafted answer is sent automatically — now the model is holding a conversation with your customer with no adult in the room
- Win-back and churn-save programs, which are marketing to people who left, going out over the domain that also carries your receipts
The events table gets a new column and a backfill to populate it, run late on a Sunday because it locks the table. Every row is rewritten and every row emits an update, and the lifecycle worker listens for updates. It is not the welcome program that fires — that one keys on creation and survives. It is the win-back, which triggers on thirty days of inactivity evaluated against a last_seen field the backfill quietly reset. Four thousand two hundred current, paying, actively-using customers receive a warm personal note from the founder address saying it has been a while and asking what went wrong. The model wrote each one individually, so there is not even a single subject line to apologise for, and the eleven replies waiting before breakfast are all some version of the same question: are you shutting down?
Is that you?
the verdict is a default, not a law
- It drafts and you send — the model writes, a person presses the button, every time, with no bulk approve
- The programs are transactional in substance: a receipt, a next step the user just triggered, a notification about their own action
- Volumes are small enough that you read every message that goes out, and you honestly do
- The provider owns suppression, bounces and the unsubscribe link, and your code only decides what to compose
- The trigger is a database state rather than an explicit event with an id and an idempotency key
- The events endpoint can be reached without authentication, or takes the recipient address from the caller
- Generated copy can reach a recipient without a person having read those exact words
- Marketing programs leave from the same domain as your password resets
- There is a bulk-approve button anywhere in the queue
If you build it anyway
the checklist, then the prompt that enforces it
- Dry run is the default, and the only way out is a per-program flag you set deliberately. A new program renders the real message for the real recipient and delivers it to you.
- One idempotency key per user, program and step, written before delivery and enforced by a unique constraint in the database. Not a cache, and not after the fact.
- Never trigger on state. Trigger on events with ids, and refuse to act on any event older than a short window, so that a backfill is inert by construction rather than by luck.
- Authenticate the events endpoint and resolve email addresses server-side from your own user table. An endpoint that accepts an address from the caller will eventually be used by somebody else to send mail from your domain.
- Hard caps per program, per hour and per address, enforced inside the sender rather than the scheduler, and enforced by refusing rather than by warning.
- Store the exact rendered body that went to each recipient. Generated copy that exists only as a prompt and a temperature cannot be investigated afterwards, and afterwards is when you will need to.
- Marketing programs send from a subdomain with its own DKIM key. Win-back is marketing however personal it reads.
I am building an automated lifecycle email system: product events in, a state
machine per user, a language model writing the copy, a provider sending it.
Assume every failure here is a message a real customer has already read, and
order the work so the irreversible parts are the safest parts.
1. Build the send gate first. Default every program to dry run: render the real
message for the real recipient, deliver it to me, log it, send nothing.
Leaving dry run is an explicit per-program action, never a global switch.
2. Then idempotency. A key per (user, program, step) written before delivery,
with a unique constraint in the database. Assume the worker gets killed
mid-run and retried, because it will be.
3. Never trigger on database state — only on events with ids. Refuse to act on
any event whose timestamp is older than a short window, and tell me this is
what makes a backfill harmless instead of catastrophic.
4. The events endpoint is authenticated, and the recipient address is resolved
server-side from my own user table. Refuse to accept an email address in the
request body, and explain that it would be an open relay on my domain.
5. Enforce caps inside the sender, not the scheduler: per program, per hour,
per address, per day. On breach, stop and raise. Never warn and continue.
6. Store the exact rendered body per recipient, with the model, the prompt and
the inputs. I need to be able to read what actually went out.
7. Ground every personalised claim in a value from my database, and refuse to
let the model infer facts about a user's behaviour. If a field is null, the
sentence is dropped rather than filled in.
8. Use an established sending provider and let it own suppression, bounces and
the unsubscribe link. Check suppression per address immediately before send.
9. Marketing programs — win-back, churn-save, expansion — send from a
subdomain with its own DKIM key, separate from my transactional mail, and
carry a working unsubscribe and a postal address in the base template.
10. Do not build automatic reply sending. Drafting a reply is fine. Delivering
it without a person reading it is out of scope, and say so.That one keeps you out of trouble. For the prompt that actually builds it, canivibecodeit.com has one.
their build prompt ↗Or don’t build it
the boring option, and the way back out
Ninety-nine dollars a month for three programs and twenty-five thousand sends is a strange thing to weigh against a weekend, because the sending is not what you are buying. You are buying an approval gate that cannot be skipped on the first send, a per-recipient render you can read afterwards, and somebody else's considered opinion about what a backfill ought to do. The split worth making is this: build the events API, which is small, honest and genuinely yours, and rent the machine that decides to press send.
$99/mo is cheaper than your weekend.
The genuinely valuable pieces are the event schema and the program definitions, and both should live in version control as plain data rather than in a database somebody edits through a UI. Keep the per-recipient send log — recipient, program, step, timestamp, rendered body — because it is simultaneously your migration record, your suppression evidence and the only way to answer "what did we actually send this person". Moving onto Customer.io, Loops or Mara itself is mostly re-pointing the event stream; what does not move is a reputation you damaged on the way.
Open-source marketing automation with a campaign builder, segments and drip flows. Heavy, but it is the real self-hosted analogue.
Open-source single-binary mailing-list and campaign manager, a sane sending substrate to build triggers on top of.
Self-hosted newsletter tool with an API, lighter to operate than Mautic.
Questions
Why is this YOUR FUNERAL when Loops and Mailchimp are ABSOLUTELY NOT?
Consent. Every address in a lifecycle system belongs to somebody who created an account with you and can be pointed at a signup record — that is the strongest position email ever puts you in, and it removes the single worst failure mode from the newsletter entries, which is a list you cannot account for. Everything else here is as bad or worse, particularly the generated copy. Import a purchased list into the same machinery and the verdict moves immediately.
The approval queue means a human reads everything. Doesn't that solve it?
It solves it on day one and stops solving it in week three. Approval queues decay in a completely predictable way: the volume rises, the drafts start looking fine, somebody adds a bulk-approve button, and within a month approval means glancing at a count. Design for that. Cap what a single approval can release, make bulk approve impossible rather than discouraged, and keep the rendered body of everything that went out so the queue is not your only line of defence.
What is the most dangerous thing to let an agent build here?
The events endpoint, if it accepts an email address from the caller. It is the natural design — post a user id and an email, get a lifecycle program — and it turns your domain into a way for anybody with the URL to send authentic-looking mail from your company to any address they choose. Resolve recipients server-side from your own user table and that entire category disappears.
Can the model be trusted to write in my voice?
Voice is the part it is genuinely good at, and it is not the part that hurts you. The risk is facts: a sentence like "since you added your third teammate last week" is fluent, personal, plausible and wrong, and it goes out over your name to someone who knows it is wrong. Bind every personalised claim to a real value from your own data and drop the sentence when the field is null.
- CAN-SPAM Act: A Compliance Guide for Business (FTC)
- GDPR Art. 7 — conditions for consent (EU)
Every week, someone ships something they shouldn’t have.
New verdicts, the worst thing that landed in the trap, and the occasional incident report. No other email, ever.
Lifecycle email means automated messages you did not personally read going to real customers.
Your reputation as a sender is an asset you can destroy in one bad loop and never rebuild.
Sending bulk email is 5% code and 95% not getting your domain blacklisted forever.
last reviewed 2026-08-05 · verdict is editorial and unsponsored · shared entry data from canivibecodeit under MIT · not legal advice