← All work

Live on the App Store · iOS · Android following on Google Play

Split Decision Live

A daily phrase puzzle with two ways to play. There's solo, which works like any daily. And there's co-op, where each of you owns a different hidden word in the same phrase, so neither one of you can finish it alone.

View on the App Store →
Split Decision solved screen showing the phrase TIME IS MONEY, with moves and streak stats and a prompt to start a co-op game Idioms puzzle mid-game: TIME solved, and HONEY submitted as a guess for the five-letter second target, with O, N, E, and Y confirmed correct and H marked wrong, matching letter feedback highlighted on the keyboard Co-op puzzle screen showing a teammate's row marked 'hasn't started yet' with a Nudge button

What it is

The category is crowded with word puzzles, so it isn't really competing on puzzles. The job it does is giving a partner or a sibling or a long-distance friend a lightweight reason to talk every day, which is why it's built for persistent groups of two or three rather than for a social network.

It's a TypeScript monorepo with Node and Prisma on Postgres, a React web app, and native SwiftUI and Kotlin clients, all deployed on Fly, with more than 1,100 tests across web and native.

The decision

One global daily phrase was serving two incompatible jobs.

The single daily phrase was the identity of the solo game, where there's exactly one puzzle a day and everybody gets the same one. It was also where team puzzles came from. That worked right up until somebody joined a second team, because the moment they've seen the phrase once, the information asymmetry the whole co-op mechanic runs on is gone: they already know the answer their teammate is working toward. So I decoupled team puzzles from the solo daily.

On metrics, the more useful part is what pressure-testing changed, and then changed again. My original North Star was Recurring Co-op Duo-Days, which counted every team-day where both members played their assigned word. On paper it's the right metric, because it only moves when co-op actually delivers.

The problem is that computing it means recognizing the same two people tomorrow, and identity in the app is per-device with no recovery. Somebody clears their data or picks up a second phone or reinstalls, and they come back as a new player, which quietly splits a returning duo into two identities. The bias runs downward, it runs hardest on the engaged pairs the metric exists to reward, and it's invisible, because you can't tell "this duo churned" from "this person got a new phone." A number that's most wrong exactly when you're most successful is worse than no number, so I declared it uncomputable until identity recovery ships.

What I put in its place at launch were two things I could measure inside a single game: how often a player spends a Signal on their teammate's word, and how often a Rescue gets claimed when someone is stuck. Both of those need both people present and paying attention in the same session, which is exactly why they survive the identity churn that broke Duo-Days.

Then I revised it a second time, because the replacement had a problem of its own. It measured whether co-op felt good for the pairs who were already there, and it said nothing about whether anybody came back. Meanwhile the North Star I'd promoted in the interim, new solo-to-co-op converts, read 1 in a week against 0 the week before, and a metric that returns 0 or 1 can't steer anything.

So the North Star is now Weekly Retained Players: individuals with at least two distinct play-days in the trailing week. Co-op didn't get demoted, it got moved, because it's the input the North Star leans on hardest, and as of late July 2026 it sits at about 6% of players. What I'd missed for two months is that team IDs live server-side and survive the device churn that broke Duo-Days, so "did this team play again within 7 days" was computable the whole time. I'd framed it as pair retention or nothing, and it was never that binary.

Two smaller ones. I derived the teams-per-user cap from an actual comprehension test instead of asserting it, because I wasn't willing to ship a possibly-confusing product on arithmetic nobody had run. And when I caught myself describing a change as "only two lines of code," I split the claim in two, because the genuinely risky part, which was cross-surface dedupe, had been getting laundered by the cheap headline.

What it cost

Bundling web assets into the native shells means giving up instant web-to-native updates. I took that trade knowingly, to avoid a rejection under App Store guideline 4.2, which bars apps that are thin wrappers around a website, and I logged live-update infrastructure as deliberate debt rather than pretending it wasn't debt.

Losing the single global phrase also cost the solo game some of its identity, and that was the price of the co-op mechanic working at all.

The bet underneath all of it is that having a partner in the game makes people come back, and I want to be straight that I could not find public evidence for it. Every precise-sounding number I chased traced back to a content farm with no attributable source. So I'm treating it as a hypothesis to test against my own numbers rather than something I can budget against.

Status & next

Split Decision is live on the App Store, with Android following on Google Play. Shipping it was never the hard part. The real question is whether the co-op loop closes, because as of late July 2026 about 6% of players had ever finished a co-op game and 17 of 65 teams had ever reached a second player. Until the invite flow converts, a wider push mostly just adds more people to the solo game.

The clearest lever is a gap at the send step: in a recent week, 52 created invites produced 2 link previews. That's either people generating links they never send, or instrumentation that isn't firing, and closing it is the first thing I want to do now that the app is out.

Account deletion hard-deletes personal data, but it pseudonymizes shared co-op records to "Former player," so one person leaving can't corrupt their teammate's history.