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.

A ledger showing only good calls would prove nothing except that we were willing to edit it.

12

decisions recorded

5

held up

6

regretted or reversed

45%

of the 11 resolved went well

  1. 4 Aug 2026

    Regret

    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 3 August 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.

  2. 29 Aug 2026

    Held

    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.

  3. 2 Sept 2026

    Held

    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.

  4. 4 Aug 2026

    Held

    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.

  5. 4 Aug 2026

    Reversed

    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.

  6. 1 Jul 2026

    Regret

    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 4 September, 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.

  7. 2 Sept 2026

    Held

    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.

  8. 3 Sept 2026

    Too soon to tell

    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 behaviour the product depends on.

    What happened

    Published on 3 September. Billing is not switched on and no one has paid anything, so there is nothing to report yet. Recorded here so that the claim is on the record before the result is known.

  9. 3 Sept 2026

    Regret

    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.

  10. 3 Sept 2026

    Regret

    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.

  11. 4 Sept 2026

    Held

    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 is computed from a database view that physically contains no title, summary or message text, so a reporting bug cannot leak decision content into a chart.

  12. 29 Aug 2026

    Regret

    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 cancelled 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.

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.