Blog · Building Hellofew, week by week, part 3 of 8

Week of 7 September 2026: the loop closes, on a fake LinkedIn first

Adarsh Mamgain · 31 October 2026

51 commits in six days, the busiest week until the launch. By Friday the whole loop existed: find people who match the profile, score them, write a message for each, put them in a queue for the customer to approve, plan the sends across working hours, send, notice an acceptance, send the first message the next working day, follow up once, notice a reply, cancel everything else for that person. It also got a deploy, a digest email, comparison pages and a legal section. It was a lot. Some of it was good.

The loop, and where a reply stops itFind people, read each one, write a message, the customer approves, the invitation is sent, they accept, a first message goes the next working day, one follow-up if they do not answer. A reply at any point cancels everything still queued for that person.FindReadWriteYouapproveSendAcceptedMessageFollowuponce They reply: everything queued for them is cancelled Checked twice: when the reply lands, and again in the seconds before any send goes out.
The loop as it was drawn that week and as it still runs. The approve step is the customer's; everything else is the worker's. The dashed line is the check that runs again in the seconds before any send.

A fake LinkedIn, and what it found

Before any of this touched a real account I built a fake one: a small server that behaves like the provider's API, accepts invitations on a schedule, replies to some messages, and refuses things the real one refuses. Then the loop was run against it for fourteen simulated days, and the baseline from that run is in the repository as a document.

The fake found three bugs that the real one would have found on a customer. The acceptance path marked a lead accepted when the provider had merely listed the invitation as sent. The reconciler counted the week from the database's clock rather than the one it was handed, so a test and production disagreed about what a week was. And the row-level policies from week one had been written for the original tables and never applied to the four added since, which the fake found because its two accounts could see each other's leads. That last one is the reason the suite now asks Postgres which tables exist rather than trusting a list.

One follow-up, and a reply that stops everything

The follow-up rule was decided this week and has not changed: one message after somebody accepts, one follow-up 4 days later if they have not answered, and nothing after that. There is no setting for a second follow-up and no column for one. The reasoning has its own post; the short version is that every product with the setting ends up being run with it turned up.

A reply cancels everything queued for that person, and it is checked twice: when the reply lands, and again in the moment before any send goes out, because a reply can arrive in the minutes between the queue being planned and the message leaving. That double check is the single line of code I would keep if I had to throw the rest away. A follow-up arriving at somebody who answered yesterday is the one output that would make a customer stop trusting the product, and it must not depend on an inbox write succeeding or a webhook arriving in time.

The breaker, and the blind window

The accept-rate breaker also arrived this week: if too few of the invitations that have had a fair chance to be answered were accepted, the daily cap halves; lower still, inviting stops. The first version had no minimum sample and stopped an account on its first morning because three invitations and no acceptances reads as zero percent. The fixed version needs 20 invitations each 7 days old. That fix created a window: for the first ten days of an account's life the breaker cannot fire at all, which is exactly when a bad profile does its damage.

The two breaker tiersFrom day four a blunt check on 10 invitations 3 days old; from about day ten the settled check on 20 invitations a week old, halving the cap under 15% and stopping under 8%.day 0day 4day 7day 10day 14 early tier: 10 invitations 3 days old, halve under 20%, stop under 10% settled: 20 a week old, 15% / 8% Before day four nothing can be judged. Between day four and day ten only the blunt check can fire. From day ten the settled one takes over.
The second tier was added on Saturday 12 September, the last working day of this week. It halves the cap under 20% and stops under 10% on a smaller, younger sample, and hands over to the settled check as soon as there is one. The thresholds are the constants the sender reads.

So on the Saturday the second tier went in, the first search was made to run the minute an account connects rather than the next morning, approving the first three people became the thing that starts sending rather than a switch on a settings page, and a rule was added that one LinkedIn flag in an account's first day of sending stops it until a person restarts it. Those three commits are the activation and safety story of the product in one afternoon, and they came out of watching a real account for the first time.

The deploy, honestly

The first deploy took eight commits on the Tuesday. Two migrations were invisible to the migration tool because they had never been registered. The mock loader was in the ignore file, so no clean clone could build. The build read environment variables that production did not have at build time. The migration script exited with code one and no message. The platform hid a one-shot job's logs, so migration moved to worker boot where its output could be read. Postgres became its own resource rather than a container beside the app. None of this is interesting and all of it is why I distrust any week with no fixes in it.

The week also produced the first comparison pages, the sitemap, the markdown twin of every page and the llms.txt that lets a model read the site, and the first version of the landing page. The limits that page published are the constants from week two, unchanged: 20 a day, 80 a week, the ramp from 5. They are on the limits page, and what the real accounts have done under them is on the numbers page.