---
title: Twins found us
description: 76% of onboardings declared twins or more, over fifty times the natural rate. How a one-baby app became twins-first, and what the jump did and didn’t prove.
url: https://secretocho.design/notes/twins-found-us/
type: BlogPosting
published: 2026-10-11
---

# Twins found us

> 76% of onboardings declared twins or more, over fifty times the natural rate. How a one-baby app became twins-first, and what the jump did and didn’t prove.

2026-10-11 · 10 min

*Part 6 of 7 in the [Building ProbaBaby](#the-series) series.*

We have one baby. Our app’s users mostly don’t.

Over the twelve weeks to 11 October 2026, 351 onboardings were completed in ProbaBaby, and in 266 of them people said they were expecting, or already had, twins or more. That is 76%.

![ProbaBaby admin chart, Twin Share of Onboardings: 266 of 351 onboardings were multiples (76%) over 12 weeks. Weekly stacked bars of singles and multiples start in mid-August, then read 48, 56, 62, 95 and 77 onboardings a week from 7 September, mostly multiples.](https://secretocho.design/_astro/twin-share-of-onboardings.C6JINeMi_Z1Jx3zU.webp)

About 1.2–1.5% of deliveries are twins; the often-quoted 3% counts babies, not deliveries. So the app’s twin share runs at more than fifty times the natural rate.

deliveries, in general

- **1.2–1.5%** twins

ProbaBaby onboardings, 12 weeks to 11 Oct

- **266** twins or more
- **85** one baby

each square is 1%

The diagram, step by step:

1. About 1.2–1.5% of deliveries are twins. The often-quoted 3% counts babies, not deliveries.
2. In ProbaBaby, 266 of 351 onboardings in twelve weeks declared twins or more: 76%.
3. More than fifty times the natural rate.

*we have one baby. Our app’s users mostly don’t.*

I didn’t plan for this audience. This part is about how the app followed the people who showed up, what it took in the code, and what the growth that came with it does and doesn’t prove.

## An afternoon in June

On 8 June 2026, less than three weeks after our own baby was born, I wrote a plan to let the app follow more than one baby at a time. All seven phases were committed between 17:04 and 18:31 that day. The What’s New text for v1.0.3, “Now with TWINS support”, was written at 20:04.

It was that fast because of one decision: don’t delete the single “current baby”, demote it. The app gained a set of active babies, and the old property stayed as the set’s “primary”, so every screen that read one baby kept working exactly as before. Simplified:

```
// June 2026: twins without rewriting every screen
@Published var activeBabyIDs: Set<UUID>     // new: every baby you follow
@Published var currentBaby: PostpartumBaby?  // kept: now the set's "primary"
```

That afternoon brought a Home card per baby, two Live Activities side by side, a baby picker on each widget and a baby picker on the Watch. Two things were left behind. The in-app timer stayed single-baby on purpose: the plan estimated 81 places in the code and called it “disproportionate risk for a live app”. And the Watch picker never appeared at all, because the phone never sent the Watch the list of babies. That second gap stayed invisible for eleven weeks.

## Then they came

After v1.0.3 went live on 12 June, almost nothing happened for seven weeks. Through June and July, about 2 of 33 new pregnancy profiles were twins. Then, in early August, the share jumped: in the four weeks to 31 August it was 18 of 25, or 72%. No release, ad, post or metadata change is recorded in early August, and nothing in the record explains what started it.

What I do know is what those families were doing. In August, twin support on the pregnancy side was one toggle in a form, and it fed a doctor’s PDF and almost nothing else. Seventy-two percent of new pregnancy profiles turned on a toggle the app barely used. They were telling the app who they were before the app did much for them.

The market explained why they might stay. The best-known dedicated twin app had a 2.1-star rating from 10 ratings and hadn’t been updated since October 2024. In August, What to Expect, the most-reviewed pregnancy app in the US store, couldn’t add a twin pregnancy at all. There’s an honest second reading too: a new app with no ratings wins very few singleton parents, who have apps with hundreds of thousands of reviews. A high twin share partly means twin families were the people for whom ProbaBaby was the best available choice.

I acted on it before I could measure it properly. The twin-first plan came on 17 August. On 26 August, six of the last ten registrations were twin pregnancies. On 31 August a new admin dashboard, its numbers checked against hand-written queries, put the four-week share at 72%.

## Twin-first, in forty hours

The plan, written on 17 August, set its goal: “Most new users are twin pregnancies, and no mainstream competitor ships real twin support.” A 13-agent analysis produced 87 findings, and one rule ran through all five phases: singleton behaviour stays bit-identical.

**Medicine in one place.** A 40-week assumption lived in Home cards, widgets, the Watch, calendar exports, PDFs, reminders and pushes. It became one struct with written sources (NICE NG137, ACOG PB 231):

- twins with two placentas, or not yet known: target 37+0 weeks;
- twins sharing a placenta, two sacs: 36+0;
- twins sharing a placenta and a sac: 33+0;
- triplets: 35+0;
- four or more: no computed date at all.

- **twins, two placentas or not yet known**: 37+0
- **twins sharing a placenta, two sacs**: 36+0
- **twins sharing a placenta and a sac**: 33+0
- **triplets**: 35+0
- **four or more**: no date

due date, 40+0: never moves.

The diagram, step by step:

1. The medical due date stays at 40+0 weeks. It never moves.
2. Twins with two placentas, or not yet known: a target of 37+0.
3. Sharing a placenta with two sacs: 36+0. Sharing a placenta and a sac: 33+0.
4. Triplets: 35+0. Four or more: no computed date at all.

*only the target surfaces change; a widget’s label switches from Due to Target.*

One invariant matters more than the table: the medical 40-week due date never moves. Only the “target” surfaces change, and a widget’s label switches from Due to Target. While building it, an old calculation turned up that had been showing twin mothers a delivery window ending at 42 weeks, the result of an arithmetic accident.

**Declare once, at the start.** Onboarding now asks how many babies, with One as the default so singleton parents tap nothing extra. A birth creates one profile per baby. A review caught a case that must never happen: after a recorded twin loss, the app must not ask “Add their twin?”

**Two babies, two safety nets.** Stopping twin A’s feeding alarm used to cancel twin B’s backstop, so alarms now carry the baby’s ID end to end. Twins fed together produce identical alarm times, so each further baby’s escalation is shifted by another 75 seconds.

**Both babies, one tap.** Log screens gained an A, B or Both chip, reminders became per baby, and a Compare view shows the two side by side, describing differences without judging them.

**Corrected age.** About 60% of twins are born preterm, so milestones and growth percentiles use age corrected to the due date until 24 months, as paediatricians do. Vaccinations always follow actual age.

**Content.** 36 twin weekly notes, now in all 32 languages, were checked against sources before translation. That check caught a week-36 note saying shared-placenta twins deliver at 36–37 weeks, which is true for one kind of shared placenta and wrong for the other. A separate fix caught the weight-gain calculator telling twin mothers to gain 5–8 kg less than their own recommended total.

## The shortcut that waited eleven weeks

One line of feedback started the hardest day: the night tracker’s Baby A and Baby B buttons “make no sense — each flow should follow its baby”. An 18-agent audit traced every twin complaint to the one layer June had skipped, the single in-app timer:

- With twin A’s left-breast feed running and Baby B selected, tapping L ended A’s feed without asking.
- After a switch mid-feed, A’s lock-screen buttons paused or ended B’s session.
- One parent starting a timer for B could end the other parent’s live feed of A, through a confirmation card that didn’t say which baby.

The audit’s summary: the app had gone per-baby everywhere except “a single per-device slot bound to one global ‘focused baby’”. A scan with plain regular expressions put the real size at 638 lines across 30 files, against June’s estimate of 81 places in 14 files.

|  | before | after |
| --- | --- | --- |
| the in-app timer | one per-device slot, bound to one “focused baby” | one slot per baby, in a separate, deterministic engine |
| the size of the change | estimated: 81 places in 14 files | scanned: 638 lines across 30 files |
| models-package tests | 75, in mid-August | 232 |

The diagram, step by step:

1. June: twins support leaves one layer single on purpose, the in-app timer, one slot for one “focused baby”.
2. June’s estimate for changing that: 81 places in 14 files, “disproportionate risk for a live app”.
3. August: an 18-agent audit traces every twin complaint to that slot. A plain scan: 638 lines across 30 files.
4. The timer moves into its own engine, one slot per baby, and the models package goes from 75 tests to 232.

*a call-site estimate is a guess until a scan says otherwise.*

The audit landed at 02:49. A six-phase plan followed at 03:40, and all six phases were code-complete by 22:10 the same day. The timer logic moved out of a 7,000-line view-model into a separate, deterministic engine with one slot per baby. Every transition takes the current time as an argument, so it can be tested. The old published properties stayed as mirrors of the focused baby, so existing screens compiled and behaved the same. Simplified:

```
// August 2026: one slot per baby; the old properties mirror the focused one
@Published private(set) var sessionStates: [UUID: ActiveSessionSlot] = [:]
@Published private(set) var activeFeedingSession: FeedingLog?  // focused baby's
```

A golden test suite transcribed from the old single-baby code had to pass before the view-model was rewired. The models package went from 75 tests in mid-August to 232. The Watch finally received its list of babies. The reviews kept earning their keep: one caught the Watch sync putting every baby’s name and feeds back on the Watch right after the user logged out, and the final review found its only two serious bugs in code written earlier that day to fix review findings. Fixes need the same review as features.

## Saying less on purpose

Some things the app deliberately doesn’t do, and a written list says never to claim them:

- **Per-baby kick counts.** Telling which twin moved isn’t reliable, and the guidance is written for single pregnancies.
- **Growth-discordance or TTTS alerts.** The Compare tab only describes; it never triages.
- **A NICU mode.**
- **Two timers on the Watch.**
- **A twin face prediction.**

The twin keywords waited too: they were held back until onboarding actually asked about twins, so “built for twins” was true from the first launch. Still, a screenshot went live saying kicks were “adjusted for one baby or two”. They aren’t, and it was caught weeks later.

## The store page

For v1.0.4 only the cheapest, most reversible fields changed. The subtitle became “Twins, kicks & AI baby face”. The name stayed “Pregnancy & Baby Tracker - PB”, with a rename held in reserve that hasn’t been needed. The metadata went out in 36 locales, each written from English rather than translated from another language, then reviewed. The Turkish subtitle packs three search phrases into a 30-character field. The review caught both Chinese versions opening on a pregnancy test’s first line, the one that on its own means “not pregnant”.

The release nearly slipped. Two days before launch, App Store Connect rejected build 108 for dropping iPad (Part 5 has that story). v1.0.4 went live on 4 September.

## The jump

The chart at the top of this post can’t show a before and after, and that’s my fault. The onboarding event it counts had no call sites until 18 August and first reached App Store users in v1.0.4, so the bars begin at the pivot. Instrument before you need the “before”.

Sign-ups show the step instead. In the three weeks before 4 September, about 1.8 people a day signed up. In the first week after, about 6.6 a day. From mid-September, about 10 a day. Users went from 194 on 12 September to more than 350 by the 27th and 486 by 11 October, and daily actives went from 36 to about 110. The onboarding chart, week by week from 7 September: 48, 56, 62, 95 and 77. The twin share held at 70–81% every week as the volume doubled, so the new traffic was the same kind of audience, not a dilution. As a cross-check, 290 onboardings in the four weeks to 11 October against 292 new users.

- **the three weeks before 4 Sep**: ≈1.8
- **the first week after**: ≈6.6
- **from mid-September**: ≈10

The diagram, step by step:

1. The three weeks before v1.0.4: about 1.8 sign-ups a day.
2. The first week after 4 September: about 6.6 a day.
3. From mid-September: about 10 a day. 194 users on 12 September, 486 by 11 October.

*the store page and the app changed together on 4 September.*

## What I can’t claim

I can’t name one cause. The store page and the app changed together on 4 September, and without App Store Connect’s source data they can’t be separated. I can rule some things out. No Apple Ads ran. No custom product page was live. The website had no analytics, no followed backlinks and nothing indexed in Bing (Part 7). The social videos have no posting record, and my messages to twin-parent creators asked for honest feedback, with no link in the first message. Nothing in the record shows App Store featuring.

And the early-August wave that started it all came before any of it, with no recorded trigger.

Installs also aren’t revenue or proof. Twin support is free by design; a second baby is never behind a paywall. Total revenue so far is $32, and the US listing still has no rating. The twins brought the app its users. The rest still has to be earned.

## What I’d pass on

1. Watch what users volunteer, not just what they use. A toggle that does nothing can still be a signal.
2. Measure before you bet, and instrument before you need the “before”.
3. Demote, don’t delete: keep the singular as the primary of a set. Then write down what the shortcut leaves single, because that is where the next bug lives.
4. Your callsite estimate is a guess until a scan says otherwise. June said 81 places; August found 638 lines across 30 files.
5. Put clinical numbers behind one choke point, and never let a derived date replace the medical one.
6. Write the “never claim” list before the marketing copy.
7. Review the fixes too.

## The series

1. [Four platforms in four months](https://secretocho.design/notes/four-platforms-in-four-months/)
2. [Rules born from mistakes](https://secretocho.design/notes/rules-born-from-mistakes/)
3. [The sheet that closed itself](https://secretocho.design/notes/the-sheet-that-closed-itself/)
4. [A newborn app, with a newborn](https://secretocho.design/notes/a-newborn-app-with-a-newborn/)
5. [What Apple, Postgres and 32 languages taught me](https://secretocho.design/notes/apple-postgres-and-32-languages/)
6. Twins found us
7. [A spotless website nobody could find](https://secretocho.design/notes/a-spotless-website-nobody-could-find/)

[cd ..](https://secretocho.design/notes/)
