Lab · Part 2 of 2 · System design · Google Apps Script + Gmail API · Nov 2026
Untangling 227,002 emails
With a brief in hand (my inbox is for people, opportunities and records) I designed and built a nine-folder system that sorts every hour, learns from one label and never deletes without a 30-day window. The inbox went from 227,002 conversations to 10,232 in six days.

The 30-second version
8 min read
Role
Designer and builder
Partner
Claude Code, for data pulls and code
Built with
Google Apps Script, Gmail API
Timeline
3–8 Nov 2026
I designed for trust before speed: every destructive step is reversible, anything that could lose a receipt or a recruiter runs on fixed rules instead of guesses, and the whole system is taught with one label from my phone. I chose precision over recall and accepted the cost: 29% of new mail still lands in a Review pile I teach down.
−95%
conversations in the inbox, 227,002 → 10,232
0
emails deleted without a 30-day window
71%
of new mail placed automatically in week one; 29% to Review
The brief
Raise signal share from 1% without risking the 1%
The research in Part 1 showed that only 1 in 100 emails needed me, and that the 1% mattered more than everything else combined: interview invites, replies from people, receipts. That made the design problem lopsided. A system that clears 99% of the noise but buries one recruiter email has failed.
My inbox is for people, opportunities and records. Everything else has to earn its place.
The design brief, 3 Nov 2026
Constraint | Why it shaped the design |
|---|---|
227,002 conversations to start | A one-by-one approach would take weeks; everything had to batch |
Apps Script stops at 6 minutes a run | Work had to be resumable, logged and safe to stop halfway |
Mid–job search | A missed recruiter email had a real cost, so Jobs had to win every conflict |
I manage mail on my phone | Any teaching gesture had to be one tap, not a settings screen |
Principles
Three principles I wrote before any code
Reversible by default. Archive, never delete. Anything headed for Trash waits 30 days in a folder I can see.
The inbox is only for action. Being labelled isn’t enough; if I don’t need to act on it, it leaves the inbox.
Teach with one gesture. Correcting the system has to be faster than ignoring its mistakes.
The system
Nine places, each with one rule
Every email gets exactly one category, and the category decides whether it stays in front of me. A label in Gmail works as a folder, so “sorted” means moved out of the inbox, not just tagged.
Folder | What goes there | Where it lives |
|---|---|---|
★ Jobs | Hiring systems, recruiters, interviews | Inbox, starred, phone alert |
People | Real people writing to me | Inbox |
Saved | Receipts, orders, flights, appointments | Inbox 30 days, then archived |
Review | Bulk mail it can’t place yet | Inbox, until I teach it |
The Information | The one publication I pay for | Own folder |
Newsletters | Substack, beehiiv and other writers | Folder |
Events | Luma, Partiful, hackathons, invites | Folder |
Courses | The learning I chose to keep | Folder |
Unwanted | Confirmed retail and spam senders | Holding folder, Trash after 30 days |
The order is the design
Each step only sees what earlier steps left alone, so what runs first wins. The order encodes my priorities.
My corrections, so I always beat the machine
Jobs, so nothing can bury a recruiter
Saved, so no later rule can trash a receipt
Known senders, from everything it has learned
Unwanted, confirmed senders only
Guesses for the rest, which land in folders, never in Trash
People: what’s left from a real address stays in the inbox
Tidy: anything older than six months is archived
Hard calls
Four trade-offs I made on purpose
Archive over delete
I chose archiving, a 30-day holding folder and then Trash over deleting on sight. It’s slower and keeps more storage, but I was only willing to let a script touch 227,000 emails because every step could be undone.
Rules over AI for anything destructive
Moving mail to Unwanted uses a fixed list of confirmed senders, never a guess, and never anything that looks like a receipt. A model would catch more, but a safety net that can make its own mistakes isn’t a safety net.
Precision over recall, at a cost
Because Unwanted only takes confirmed senders, 289 threads in the first week (29%) landed in Review instead. I accepted a bigger pile to teach over a single wrongly trashed email.
My mental model over the technically correct one
Version 1 labelled everything correctly and left it in the inbox. To me, nothing had happened. I changed it so reading folders leave the inbox, because a working system that feels broken is broken.
Every state
Designing the moments when it goes wrong
A script that runs every hour on 227,000 emails will fail. The design work was deciding what failure looks like from my side.
State | What I see | How I recover |
|---|---|---|
Before any change | A dry run: what each rule would move, and how many | Fix the rule before it touches anything |
Wrong folder | An email somewhere it shouldn’t be | Move it and add Learn; three consistent fixes make it permanent |
Run out of time | A log that says where it stopped | Run it again; it continues where the mail is still unsorted |
Gmail refuses a batch | A count of skipped emails | Retries one by one; the rest of the run continues |
Something trashed by mistake | It’s still in Unwanted for 30 days | Move it back or star it; starred mail is never trashed |
Every Sunday | A report: inflow per day, share from people, what it learned | Decide what to unsubscribe from |
One label teaches it. The first version had seven “Teach” labels. On my phone that looked like homework, so I collapsed them into one: Learn, meaning “remember what I just did.”
What broke
Most of the design happened after version 1 met real mail
What I saw | What I changed |
|---|---|
The “people” rule matched nothing: Gmail’s Primary tab is | Every rule now runs read-only against the real mailbox before it can change anything |
Football promos were kept as receipts because “ticket” counted as a receipt word | Every protected word has to earn its place; “ticket” was removed |
The first full run labelled 600 emails, then ran out of time | Sort the last 6 months; archive everything older in bulk, 500 at a time |
One email Gmail refused to change stopped the whole run | Refused batches retry one by one, skip what Gmail won’t change, and report the count |
About 400 emails a run meant days to catch up | Every label and move uses the batch API; only guessing stays slow |
A six-minute run ended with an empty log | Each step logs as it finishes; runs stop themselves at 3½ minutes |
Measuring it
Week one, by where the system put it
Once it was sorting every hour, I counted every thread that arrived from 1 to 7 November and where it landed.
Measure, week one | Value | Read |
|---|---|---|
Placed automatically | 717 of 1,006 (71%) | Everything except Review |
Sent to Unwanted | 64 (6%) | Confirmed senders only, so low by design |
Left in Review | 289 (29%) | The cost of precision, and the main backlog |
Jobs and people kept in front of me | 10 | 1.0% of inflow |
Outcome
An inbox I can read again
Measure | Before | After | When |
|---|---|---|---|
Conversations in the inbox | 227,002 | 10,232 | 2 → 8 Nov |
After the first bulk archive alone | 227,002 | 25,712 | 3 Nov |
The Information in the inbox | ~300 | 2 | 3 → 6 Nov |
Job emails found and labelled | — | 603 | All time |
Emails deleted without a 30-day window | — | 0 | By design |
Phone alerts now come only from Jobs. What arrives in the inbox each day is mostly the 1% that needs me, plus the Review pile.
Not solved
Sorting isn’t the same as fewer emails
About 144 threads still arrive every day; the system only decides where they land. At a conservative 3 seconds a glance, that’s 7 minutes a day and about 44 hours a year spent on mail I don’t open.
Next version | Target |
|---|---|
Extend the one-click unsubscribe list from Unwanted to any sender opened less than 5% of the time in 90 days | Inflow under 30 a day |
Teach Review down with the Sunday report | Review under 10% of inflow |
Track signal share weekly | From 1% to 25% |
The 3-second glance is an assumption, not a measurement.
Reflection
Reversibility bought the trust to go fast
I could let a script touch 227,000 emails in days, not weeks, only because nothing it did was final. That’s the principle I’m taking into product work: reversibility buys trust, and the user’s mental model beats the technically correct one.
What I’d change: I sorted for days before I counted what arrived. Measuring inflow on day one would have pointed me at the real problem, too much mail, sooner.