Lastest

Ship fast. Don't break things.

Visit Website
May 5, 2026 How We Built Lastest to Be Self-Testing

We build Lastest the same way our users build their products: half plan, half vibe, mostly in a hurry. That worked for shipping the first version. It absolutely did not work for shipping the tenth version.

Every time we upgraded a base image, swapped a Helm chart, or let the agent refactor "just one little thing," our Kubernetes deploys would find a new and creative way to break. Sometimes the dashboard rendered fine but the diff worker silently dropped jobs. Sometimes a chart rolled out green and the API gateway 504'd under real traffic. Vibe-coding got us most of the way to a feature; it routinely got us 0% of the way to a stable release.

So we did the obvious thing in retrospect, and the unobvious thing at the time: we pointed Lastest at Lastest. This post is how that loop actually works, and what it caught that nothing else did.

The problem: vibe-coding is a feature factory, not a release engine

The pattern was always the same. Claude Code or Cursor would happily write the feature. The kubectl apply would happily roll. The pods would happily come up. And then, four hours later, a real user would happily file the bug we should have caught.

The breakages clustered into three buckets:

  • Version-upgrade rot. Bumping Postgres, Playwright, or the Next.js minor would silently change a behavior that no unit test covered - but a real screenshot of a real page would have caught instantly.

  • Cross-service drift. The frontend assumed v3 of a payload while the worker had been quietly upgraded to v4 by an agent two PRs ago.

  • Load-only failures. Everything green at 10% utilization. At 80%+ CPU and queue saturation, races appeared, sockets dropped, and the diff worker would deadlock against itself.

Happy-path E2E tests caught roughly none of those. We had to build a test layer that ran on the same substrate the product runs on, against real load, after every deploy. And the cheapest way to do that turned out to be the product itself.

Step 1: expose Lastest to itself via MCP

Lastest already ships an MCP server with 29 tools - run_tests, review_diff, approve_baseline, get_impact, the works. We exposed that same surface to our internal coding agents and to a dedicated CI agent that has nothing to do but watch our own staging cluster.

The MCP server is the seam. It means the agent that writes a Lastest feature is talking to the same tool surface that tests Lastest. No translation layer, no flaky shell scripts wrapping kubectl exec. Just typed tool calls that succeed or fail loudly.

Step 2: stop pretending happy-path tests are testing

The single biggest unlock was admitting that "click the button, see the page render" is not a test of a production system. It is a test of a demo.

Step 3: catch the niche stuff - bugs that only appear above 80% load

This is the part that surprised us most. Once we were running visual regression against a deliberately overloaded staging cluster, we started finding bugs that no unit test, no integration test, and no LLM code review would ever flag:

A WebSocket reconnect storm that only triggered when the API pod was at >85% utilization. The dashboard looked fine; the live-update indicator silently stopped updating. A visual diff caught the missing "live" badge.

A baseline-approval race where two reviewers approving simultaneously under load produced two divergent baselines stored under the same hash. Caught by a structural diff against a known-good post-approval state.

A Helm chart upgrade that flipped a default terminationGracePeriodSeconds from 30 to 5. At low load, nobody noticed. Under sustained load, in-flight diff jobs were killed mid-render and re-queued, producing flickery half-screenshots that our perceptual diff engine flagged as "novel."

A Postgres minor-version bump that changed the default sort order on a query without an explicit ORDER BY. Tests passed. The dashboard's "recent runs" list silently rearranged. A pixel diff lit up like a Christmas tree.

None of these are happy-path bugs. None of these are bugs an agent writing a Playwright test from scratch would think to cover. All of them shipped to staging at some point, and all of them were caught before production because Lastest was watching itself the whole time.

Step 4: make version upgrades boring

The biggest cultural change was that version upgrades stopped being scary.

Before: bump Playwright minor, hold breath, deploy, watch Sentry, get paged at 2am, revert. After: bump Playwright minor, let the self-test suite replay 200 journeys at p80 load against a staging cluster running the new version, read the diff report, ship if green.

The agent does the boring part. It calls get_impact, runs the affected areas, classifies the diffs, and only escalates the ones where it can't decide. Most upgrades land with a one-line PR comment: "All 200 baselines stable under p80 load. Approving." The ones that don't are the ones where you actually want a human to look.

What it took to actually do this

We did not build any of this from scratch. The pieces were:

  • The MCP server - already shipping in Lastest. We just pointed our internal agents at it.

  • A load generator - k6 holding the staging cluster at a configurable utilization band while replays run.

  • Three diff engines - pixel, structural (SSIM), and perceptual (Butteraugli) - because under load, "different" means different things at different layers.

  • Branch-isolated baselines - so a feature branch can't corrupt main's known-good state, even if the agent is wrong about whether a change was intentional.

  • One CI agent with nothing to do but watch staging, run the suite, and post diffs to the PR.

That's the entire stack. None of it is novel; the leverage came from connecting the pieces with MCP so an agent could drive them.

The shape of a self-testing product

The thing we keep coming back to is that this only works because the product's own tool surface is rich enough for an agent to use it without inventing anything. If our test loop required the agent to write Playwright from scratch each time, we'd be back to flaky selectors and 6-attempt token burns. Instead, the agent picks an area, fires a deterministic replay, and reads a structured diff. The agent is the conductor; Lastest is the orchestra. Including when the orchestra is playing a piece about itself.

We are not done. The next thing we want is replay-under-chaos as a first-class profile, where we deliberately drop a pod mid-replay and see whether the visual state recovers cleanly. That's a level of testing nobody asked us for, and it's the level we now expect from ourselves before we let anything roll to production.

If you want to do something like this on your own product, the MCP server and self-hosted dashboard are at github.com/las-team/lastest. The hosted version is at app.lastest.cloud. The point is not that you have to use Lastest specifically - the point is that "your product tests itself, on the same substrate it runs on, under real load, with an agent driving the loop" is achievable with off-the-shelf parts. We just needed a few bad deploys to figure that out.

Comment

About

I never trusted AI, even if I let it code and ship without reviewing the code. Why would I trust AI written tests? Manual testing becomes more and more of a strain, so I came up with Lastest.