ShipFlow
ShipFlow is our own product: a multi-tenant platform that takes a customer ticket and walks it through requirements, task breakdown, a developer board, and finally a pull request that two AI models review before a human opens it. The pitch is automation. The engineering is mostly not about AI at all. It is about isolation, unreliable webhooks, and jobs that run for minutes when the web expects milliseconds.
Tenant isolation is enforced in Postgres, not in application code. That was a deliberate trade. Database-level isolation is slower to build and harder to debug than a where-clause, but it means a bug in application code cannot hand one tenant another tenant's data. The database refuses. For a product holding customer requirements and code, we did not want that guarantee resting on every developer remembering every filter, forever.
The GitHub App integration assumes failure. Webhooks get dropped, duplicated, and delivered out of order, so handlers tolerate repeats and missed events can be replayed on demand. Generation runs as a background job pipeline on Inngest, with retries, because long-running work does not belong in a request handler. Then the review step: every PR is checked against the ticket's acceptance criteria by two models from different vendors. Two reviews cost more than one. We pay it, because a model marking its own homework is a weak check. A human still opens every PR. ShipFlow is in private beta, which means we are still finding its sharp edges ourselves. That is the honest status.
- Multi-tenant isolation enforced at the database layer, where application bugs cannot undo it
- Webhook handling that survives drops, duplicates, and out-of-order delivery, plus on-demand replay
- Long-running AI generation run as durable background jobs with retries, kept out of request handlers
- Cross-vendor AI review against written acceptance criteria, with a human making the final call
1600 × 1040 · dark UI