Vibe coding throwaway prototypes: when the tool deletes it for you
Most advice on throwaway vibe-coded prototypes treats deletion as a willpower problem. "Remember to throw it away." That advice is dishonest. Prototypes you intend to delete almost never get deleted. The honest fix is structural: pick a tool whose default lifespan matches your demo, so the artifact expires whether you remember or not.
Direct answer (verified 2026-05-01)
Vibe code a throwaway prototype when the requirements are unclear and the spike will take hours rather than weeks. Pick a tool whose default lifespan matches the demo. mk0r's sandbox auto-expires after one hour, set in source as E2B_TIMEOUT_MS = 3_600_000 at src/core/e2b.ts line 33. No account to clean up afterwards.
The willpower fix has a 100% failure rate
Walk through the standard advice and notice what it asks of you. Andy Hunt's prototyping rule, repeated for 25 years now, is "if you cannot bring yourself to throw the prototype away, stop prototyping and start writing tracer code." That rule lands the responsibility on the human. The Uizard guide to throwaway prototyping says the same thing in nicer words. Most of the recent vibe coding essays do too.
The problem is that the prototype, if it works at all, has already done its job by the time you should delete it. The stakeholder has seen the demo, the boss has said "can we just ship that", the friends in the group chat are using the URL. At T+24 hours nobody wants to delete a working thing. By T+1 week, the prototype has a name. By T+1 month it is production.
That is not a discipline failure. It is a default-state failure. The default state of a thing that runs is to keep running. If you want the artifact to die, something other than you has to kill it.
What "structurally throwaway" looks like in source
mk0r is the project I work on, and the choices below are the ones I made when building it. They are also the part nobody else who writes about vibe-coded throwaway prototypes seems to cover, because most of those essays are about Cursor, Replit, and Claude Artifacts, none of which expire the artifact for you.
Four constants do all the work. The 1 hourE2B_TIMEOUT_MSis the wall-clock cap on the sandbox itself, enforced by E2B, not by application code. The 45 minutePOOL_MAX_AGE_MSis the pool reaper that sweeps unused warm sandboxes before E2B does. Thecrypto.randomUUID()is the anonymous session: there is nothing tying the prototype to an email or an account row. TheFREE_MODEL = "haiku"is what keeps the throwaway free, so the on-ramp is short enough that the spike is cheaper than thinking about whether to build it.
One throwaway session, end to end
Here is how the four expirations land on a single Friday afternoon spike. Times are wall clock from when you opened the tab.
Open mk0r.com
Anonymous session key generated client-side via crypto.randomUUID(), stored in localStorage. No email, no signup.
Sandbox boots, T0
Fresh E2B sandbox created with timeoutMs of 3,600,000. The 60 minute clock starts now.
T+45 min
Pool reaper marks any unused warm sandbox stale (POOL_MAX_AGE_MS in src/core/e2b.ts) and kills it.
T+60 min
E2B itself enforces the wall-clock cap. The sandbox is killed by the platform. Your prototype is gone.
What this looks like for the maker
A real example, drawn from a session I ran last week. I wanted to test whether a tip calculator that supports split-by-percentage would feel useful, or whether it would feel like overengineering for a use case people already handle by mental math.
11:02 — open mk0r.com on phone, type "a tip calculator that splits unevenly"
1/5T+0. Anonymous session UUID is in localStorage, sandbox is already booting in the pool.
The spike answered the question. People wanted the tax override more than the uneven split. The artifact was meant to die, and it did. I did not have to remember to delete it, unsubscribe from a marketing email, or revoke any tokens. The closed tab was the deletion.
The counterargument
The honest pushback on this whole framing is: a throwaway prototype that auto-deletes is bad if you change your mind mid-demo and want to keep it. That is a real cost. The mitigation is the explicit Publish action, which detaches the artifact from the throwaway sandbox lifecycle and gives it a stable subdomain. But you have to actually click it. If you forget, the work is gone at T+60 min.
That asymmetry is the whole point. The default is throwaway. The keep-it path requires intent. If your spike turns out to matter, you can choose to keep it. If it does not, you chose nothing and it goes away on its own. The cost of forgetting to keep something good is much lower than the cost of forgetting to delete something bad. Most software tools default the wrong way around.
So when should you do this
Three conditions, roughly in order of importance.
- You have a question about the design that you cannot answer by sketching. The prototype is the cheapest way to run the experiment.
- The cost of being wrong about the requirements is greater than a few hours of vibe coding. (If your team would have built the wrong thing for two weeks, this is true.)
- You can pick a tool whose default lifespan is shorter than the time it would take to talk yourself into shipping the prototype as production. For most people that window is less than a day. The 1 hour mk0r cap is well inside it.
The fourth, unstated condition is that you treat the result as information, not as code. The artifact is not the asset. What you learned from watching it run is the asset. If the spike worked, write the real thing using a real stack. If the spike did not work, the deletion already happened on its own.
Want a throwaway-by-default vibe coding tool?
Open mk0r.com and start typing. The sandbox dies in an hour either way. Or book a call to talk through your spike.
Frequently asked questions
When should I vibe code a throwaway prototype instead of writing a spec?
When the requirements are unclear and the spike will take hours rather than weeks. The whole reason to throw it away is that you are buying information about what to build, not the build itself. If you can answer the design question by hand-sketching, do that. If you cannot, a vibe-coded prototype that runs in the browser usually exposes the wrong assumption faster than any document. The rule of thumb a few people across DEV.to and Markus Borg's IEEE prototyping playbook converge on is: spike for a day or two, throw it away, then write the real version using the lessons. Do not try to grow the spike into the production app.
What is the actual mechanism that makes a mk0r prototype throwaway?
Three things, all in source. First, the sandbox is created with E2B_TIMEOUT_MS = 3_600_000 at src/core/e2b.ts line 33. That is one hour. The platform itself kills the sandbox at the wall-clock cap. Second, a Firestore-backed pool reaper at src/core/e2b.ts line 1896 declares any pool entry stale at POOL_MAX_AGE_MS = 45 * 60 * 1000 (45 minutes) and reaps it. Third, the session is anonymous: crypto.randomUUID() in localStorage at src/app/(landing)/page.tsx line 47. No email, no payment, no row in any users table you would need to delete later. You cannot accidentally let it linger.
Where do throwaway vibe-coded prototypes actually go wrong?
Almost always: the prototype was good enough to demo, the stakeholder said "can we just ship that?", and three months later it is in production with no tests, the auth is a localStorage flag, and the data layer is a JSON file in the deployed bundle. Several writers have written this post by now (the dev.to "why shipping vibe-coded prototypes breaks products" piece is one). The fix is not to vibe code less. The fix is to pick a tool whose defaults make shipping the prototype actually annoying, so you have to consciously port it instead of accidentally promoting it. mk0r's hour-long sandbox is one such default. If you want to keep the artifact, you have to publish it explicitly.
Can I keep a mk0r prototype past the 1 hour cap?
Yes, but you have to choose to. Sign in (the anonymous session migrates to your user record) and click Publish, which provisions a stable subdomain and detaches the artifact from the throwaway sandbox lifecycle. The point is that this is a separate, deliberate action. The default path is throwaway. The save-it path requires intent. That asymmetry is what keeps the prototype actually disposable when you do not commit to it.
What about saving the source code from a throwaway run?
Each session boots a fresh git repo inside the sandbox during prewarm (ensureSessionRepo, src/core/e2b.ts). While the sandbox is alive you can pull the code or copy it out. Once the sandbox is killed at T+60 min the working tree is gone. If you treat the code as the artifact, save it before the wall clock hits zero. If you treat the running demo as the artifact, you do not need to save anything: the URL stops working, the friends who saw the demo already saw it, and the lesson the spike was meant to expose is now in your head.
Why is anonymous-by-default load-bearing for a throwaway use case?
Two reasons. One: account creation is the friction that turns a 30 second "let me try this" into a 5 minute "do I really want to give them my email for a thing I am going to delete?" Throwaway loops only stay tight if the on-ramp is shorter than the value of the spike. Two: an account is itself something you have to remember to clean up. Anonymous sessions cannot leak to the wrong inbox, cannot trigger marketing emails six months later, cannot become an attack surface. The keyboard shortcut for deleting your data is closing the tab.
What is the model that runs by default on a throwaway session?
Claude Haiku. Set as FREE_MODEL = "haiku" at src/app/api/chat/model/route.ts line 5. Haiku is fast enough that the streaming preview keeps up with you typing, and cheap enough that the platform can serve anonymous prototypes without metering the user. Switching to a stronger model requires signing in (the route returns a 402 with subscription_required for anonymous users on non-Haiku models). The signup gate is on model selection, not on building. That ordering matters: the first prototype is free, throwaway, and finishes streaming before you blink.
Is throwaway prototyping different from one-shot prototyping?
Adjacent but not the same. "One-shot" describes the input shape: you typed once, you got an app. "Throwaway" describes the output's intended lifespan: the artifact is meant to die. mk0r supports both at the same time because the structural answer to one (anonymous, prewarm) is also the structural answer to the other (no account to clean up, sandbox dies on its own). Most other AI app builders make one of those two cheap and the other expensive: signup-gated tools have throwaway artifacts but a sticky account; download-the-zip tools have throwaway accounts but artifacts that live forever in your downloads folder.
What is the honest limit of vibe-coded throwaway prototypes?
State, auth, and anything where being wrong has real consequences. The prototype is HTML, CSS, JavaScript, and whatever lives in the sandbox. There is no production database, no real auth, no payment processor, no audit trail. If the spike is to test "does this layout make sense" or "does this flow click for the user", you will get an answer in an afternoon. If the spike is to test "will this scale to 50,000 paying customers", you will not, and you should write the real version. We have a separate guide on where vibe coding stops carrying that goes into the failure modes in detail.
More on the sharp edges of vibe coding
Where vibe coding stops carrying
State, auth, and the iteration wall: the three places vibe-coded apps stop being free.
AI app builder one-shot prototype limits: the 7 clocks
The real cap on a one-shot prototype is not context window. It is seven concurrent runtime timers.
Vibe coding feedback loop iteration
Why the loop tightens or breaks, and what kills it on most AI builders that are not throwaway-by-default.