Our own ledger
We have no customers to show you. Here is our own record instead.
Every decision below was made while building Decize. The outcomes are what actually happened, not what we hoped would. 6 of the 11 that have resolved went badly, and two of those were reversed the day after they were made.
- decisions recorded
- 14
- held up
- 5
- regretted or reversed
- 6
- too soon to call
- 3
45% of the 11 resolved decisions went well.
- RegretAug 4, 2026
Run the inbound retry on a fifteen-minute cron
Schedule /api/cron/inbound-retry at `15 * * * *` so a message that failed triage is picked up within the hour.
Why, at the time
Email capture was about to become the main way decisions arrive, and a queue that drains once a day would make the channel feel broken.
What happened
Vercel’s Hobby plan refuses any cron that runs more than once a day, and it rejects the deployment at creation — so no deployment record is ever produced. The dashboard showed nothing wrong and the live site quietly kept serving the August 3 build for twenty-six days. Roughly four weeks of merged work, including the entire email capture path, was never actually in production.
Lesson. A merged branch is not a deployed one. Verify against the running site, not against git.
- HeldAug 29, 2026
Drain the queue inside the request instead of buying Vercel Pro
Move the retry cron to daily and have the inbound webhook drain up to five pending messages via `after()`, once the 200 is already on its way back.
Why, at the time
Restoring sub-daily schedules costs money. That is a spend decision, and it should not be made by accident to work around an engineering constraint.
What happened
The channel stayed responsive on the free plan. A stuck message no longer waits a full day while mail is still arriving, and the runbook records the constraint so the next person does not rediscover it.
- HeldSep 2, 2026
Ship the Content Security Policy in report-only first
Deploy the CSP as report-only, watch it, and promote it to enforcing only once the reports came back clean — keeping an environment variable to demote it again.
Why, at the time
An enforcing CSP that is wrong breaks the site for everyone at once, and the failure mode is silent for anyone not watching a console.
What happened
Report-only ran clean, the policy was promoted to enforcing, and nothing broke. The escape hatch has not been needed.
Lesson. Ship the observation before the enforcement.
- HeldAug 4, 2026
Become organization-only and drop the individual product
Make an organization workspace mandatory. Remove the personal-journal product rather than maintaining both.
Why, at the time
The individual and team products were pulling the data model in opposite directions, and the research said the individual framing had a retention problem we had no answer for.
What happened
The model simplified sharply — every decision now belongs to an organization, and row-level security has one rule to enforce instead of two. It has held with no pressure to reverse it.
- ReversedAug 4, 2026
Make the application unable to read captured email content
Add row-level security (migration 0029) so that even the application could not read the body of a captured message.
Why, at the time
Handing a product your inbox is the moment you should be suspicious of it, and a guarantee enforced by the database is worth more than a promise in a policy.
What happened
The organization-only migration two changes later dropped the policies, the function and the column, and nobody noticed at the time. The guarantee is gone; the site now says plainly that every active member can read the ledger and the captured mail behind it.
Lesson. A guarantee a later migration can silently remove was never a guarantee. If it matters, something has to fail loudly when it disappears.
- RegretJul 1, 2026
Build Slack capture
Build a Slack slash-command handler so decisions could be captured without leaving chat.
Why, at the time
Slack is where the discussion already happens, and asking people to open another tab is how decision tools die.
What happened
The handler was built and never given a way for anyone to actually install it. Zero installations exist. It was removed from every piece of marketing on September 4, two months after it was written.
Lesson. An integration nobody can turn on is not a feature. Ship the entry point or do not ship the integration.
- HeldSep 2, 2026
Leave two security-advisor warnings unfixed, on purpose
Accept that anonymous callers can execute two SECURITY DEFINER functions, and document why in the migration instead of revoking the grant.
Why, at the time
Revoking it breaks anonymous reads across nine tables that rely on those functions inside their own row-level security policies. The advisor flags the shape, not the consequence.
What happened
The grant stayed, the reads kept working, and the reasoning now sits in the migration where the next person to see the warning will find it.
Lesson. An advisory warning is an input to a decision, not a decision.
- Too soon to tellSep 3, 2026
Price on decisions, never on seats
Meter the product on decisions recorded per month, with unlimited people on every plan, and never charge per user.
Why, at the time
A decision record is only worth keeping if everyone who makes a decision writes it down. Per-seat pricing gives you a reason not to invite people, which attacks the one behavior the product depends on.
What happened
Published on September 3. Billing was not switched on at the time and no one had paid anything, so there was nothing to report yet. Recorded here so that the claim is on the record before the result is known.
- RegretSep 3, 2026
Lead with “decision intelligence”
Use “Decision Intelligence for Organizations” as the tagline, the page title and the meta description.
Why, at the time
It sounded like an established category, and being in a category people already search for seemed safer than inventing a name.
What happened
It is an enterprise business-intelligence category owned by companies with sales teams and a decade of backlinks. Unwinnable for a product with no customers, and the traffic it does attract is looking for dashboards. Replaced the next day with the terms an operations lead actually types.
Lesson. Picking a category you cannot rank in is choosing to be invisible in a respectable-sounding way.
- RegretSep 3, 2026
Ship a three-thousand-word landing page
Publish a ten-section landing page that answered every objection a buyer might raise, in full, with the real numbers.
Why, at the time
The product asks people to hand over their email and trust a ledger. Honesty in that much detail felt like the differentiator.
What happened
Roughly half the page’s height was objection-handling placed before any reason to want the product, and the section that makes anyone want it sat at sixty-five percent scroll depth. Cut by forty-seven percent the following day, with the detail moved to a second page rather than deleted.
Lesson. The problem was never the length. It was answering questions the reader had not asked yet.
- HeldSep 4, 2026
Delete the per-member analytics screen rather than hide it
Remove the screen that showed one person’s decision record, and withhold any rate that could be traced back to an individual below five data points.
Why, at the time
A decision ledger is one product decision away from becoming an employee-monitoring tool, and a screen that merely sits behind a flag can be turned back on by anyone in a hurry.
What happened
The screen is gone rather than disabled. The organization dashboard computes its rates from a database view that physically contains no title, summary or message text, and looks titles up separately to label the decisions it lists.
- RegretAug 29, 2026
Run the dependency audit as an advisory CI step
Add `npm audit` to the verify workflow with `|| true`, so a known vulnerability in a transitive dependency is visible without blocking unrelated work.
Why, at the time
Blocking every pull request on a third-party advisory we cannot fix teaches people to ignore the pipeline.
What happened
The step talks to the registry and hung twice in a row, taking the whole job to its fifteen-minute timeout. Two runs reported as canceled even though lint, type-checking, the tests and the production build had all passed — and both commits were already live. Fixed with a two-minute timeout on the step.
Lesson. `|| true` guards against a non-zero exit, which was not the failure mode. An advisory step needs a timeout, or it is not advisory.
- Too soon to tellSep 11, 2026
Put the inbound retry back on an hourly cron
Restore `/api/cron/inbound-retry` to `15 * * * *`, cut its staleness window from 30 hours to 4, and take the Hobby assumptions out of the code and the runbook — while keeping the in-request drain that was built to compensate for them.
Why, at the time
The project had moved to a Vercel team on the Pro plan, which allows a cron every minute rather than once a day. The daily schedule, the ±59-minute slack the staleness windows were sized for, and the comments explaining all of it were compensating for a constraint that no longer applied. Leaving them was the real risk: a stale platform assumption written into the code is precisely what produced the twenty-six-day outage, and the second reader has no way to tell a live constraint from an expired one.
What happened
Committed on September 11. Whether an hourly retry measurably shortens how long a stuck message waits cannot be known yet — there was too little inbound volume to observe at the time. What is already true is narrower: a test now fails if a schedule in vercel.json and its staleness window in the code disagree, which is the drift that left an hourly job with a thirty-hour window in the first place.
- Too soon to tellSep 11, 2026
Reverse the promise that going over never blocks capture
Refuse new decisions once a workspace has spent its monthly allowance — in the app, over email, on every path that writes a record — and email the owner once at ninety percent of the allowance and once at the wall.
Why, at the time
The published promise was that the allowance was a meter and never a lock, on the reasoning that the hard part of this product is getting teams to log decisions at all. That reasoning held while nobody could pay: refusing a write that no amount of money could unblock is not a price, it is breakage. Once Checkout existed the refusal had a way out, and an allowance nobody is ever held to is a price list rather than a price.
What happened
Shipped and deployed on September 11 behind two conditions, so it stayed inert until the limit was switched on AND a checkout could actually complete. Nothing had been refused at the time — the only workspace was at seven of ten decisions for the month — and nobody had paid. This supersedes the September 3 pricing entry, written while billing was still off. Two things did not survive contact: the meter counted the decision rows that still existed, so deleting one refunded allowance and the limit could be spent over and over, which took a database trigger and a counter that only climbs; and the environment variable that arms the limit turned out to arm every paid-feature gate as well, so the same deploy closed export, import and the weekly and monthly reports for that workspace, which nobody had decided to do that day.
Lesson. A meter can count what is there. A cap has to count what happened — the moment a number can refuse a write, deleting a row becomes a way to buy another one.
About this page
What this is, and what it is not.
These are real decisions, checked against the commit or database migration that carries each one before it was written down. Nothing here is illustrative.
It is not a live export from a Decize workspace. Our repository is private, so commit references would be links you could not open — evidence you cannot check is decoration. What is printed instead are the specifics: dates, durations and exact constants, which are the parts that would be awkward to invent. If we ever open the repository, every entry gets a link and this page becomes something you can verify rather than something you have to take on trust.
It will get less flattering, not more. The honest thing about a decision ledger is that it accumulates the calls you would rather forget, and the forecast on the pricing decision above has not resolved yet.
By the Decize product teamReviewed September 26, 2026