Val Town, the hosted platform for small TypeScript functions ("vals"), is shutting down. Founder Steve Krouse announced the wind-down on November 10, 2026. Code goes read-only on December 10, 2026, and every service stops on January 10, 2027. If you have HTTP endpoints, cron jobs, email handlers, or data on Val Town, the date that matters most is December 10: after that you can't change code or add val.run redirects.
The rest of this guide covers the timeline, a triage plan for each type of val, where each piece can go, and the data export steps people tend to get wrong.
The Val Town shutdown timeline
These dates come from the official announcement:
| Date | What happens |
|---|---|
| November 10, 2026 | New signups and plan upgrades end. Billing is paused. |
| December 10, 2026 | Read-only mode begins. SQLite and blob storage are excluded and stay writable. |
| January 10, 2027 | All other services end. |
| February 1, 2027 | Val Town is open-sourced. |
On why, the post says Val Town "couldn't compete in the cloud computing space." Existing subscriptions keep running for free until the end, and people who prepaid for an annual plan will get a partial refund. The post doesn't say how the refund is calculated. RuntimeWire's report notes that the platform ran for about four years.
Two details in the migration docs are easy to miss:
- Vals keep running until January 10, even though code freezes on December 10. A working cron won't stop early, but you can't fix it after December 10.
- Moving to Deno elsewhere doesn't solve anything long-term. Val Town runs on Deno, and the docs say Deno is also winding down, with core maintainers not supporting it beyond October 2027. That follows the Deno team joining Cloudflare, announced October 9, 2026. Val Town recommends moving to Node, Bun, or a provider runtime such as Cloudflare Workers or Vercel Functions.
The announcement of the February 1 open-source release doesn't say which parts will be published or under what license. Don't plan on self-hosting Val Town to keep production workloads alive.
Step 1: Take inventory before December 10
Most accounts hold a mix of things that matter and things that don't. Sort them before you spend time on migration:
- List every val by trigger type: HTTP, cron, email, or script/library. Libraries matter because other vals import them through
esm.townURLs. - Mark what other systems depend on. That includes any
*.val.runURL used as a webhook target (Stripe, GitHub, Slack, Telegram), embedded in a site, or shared with users. - Find your stateful vals. Anything that uses
std/sqliteorstd/blobneeds a data migration, not just a code copy. Check whether each database or blob store is val-scoped or account-global. - Record environment variable names. You'll recreate them on the new host. Keep the values out of any repo.
- Sort each val into one of three buckets: migrate, archive (export the code to Git and let it die), or delete.
The docs suggest letting an AI coding agent do the inventory. Install the Val Town plugin or MCP server, then ask the agent to list your vals, propose a destination for each, and wait for your approval before acting. The migration page includes a ready-made prompt for this. Only give an agent write access to production systems after you've reviewed its plan.
Step 2: Pick a destination for each piece
Val Town bundled hosting, a database, blob storage, cron, inbound and outbound email, and access control into one product. On most other platforms you'll put that bundle back together from several services. According to Val Town's own where-to-migrate guide, Cloudflare is the most feature-equivalent target, and the Val Town team is moving its own blog and docs there.
| Val Town feature | Cloudflare | Vercel | Lightweight option |
|---|---|---|---|
| HTTP vals | Workers | Functions | Render, Railway, Fly.io |
std/sqlite |
D1 (or Turso) | Turso or Postgres | Turso (Val Town's SQLite already runs on it) |
std/blob |
R2 | Vercel Blob | S3, Supabase Storage |
| Cron vals | Cron Triggers | Cron Jobs / Schedules | GitHub Actions |
| Email vals (inbound) | Email Routing | Resend Inbound (external) | Postmark, Mailgun inbound |
std/email (sending) |
Email Sending | Resend (external) | Amazon SES, Postmark |
Private val.run access |
Cloudflare Access | Deployment Protection | Tailscale |
Check the free-tier limits
The free tiers vary most on scheduled jobs, which is where many Val Town users run small automations:
- Cloudflare Workers Free allows 100,000 requests per day, 10 ms of CPU time per request or cron run, and 5 Cron Triggers per account. Workers Paid raises that to 250 cron triggers, with up to 30 seconds of CPU per run for sub-hourly schedules, per Cloudflare's limits page.
- Vercel Hobby allows 100 cron jobs per project, but each can run only once per day, and timing can drift by up to 59 minutes. Expressions that run more often fail at deploy time, according to Vercel's cron documentation. Pro allows once per minute. The same page says Cron Jobs are a legacy feature that will move to Vercel's newer Schedules product.
- GitHub Actions scheduled workflows run at most once every five minutes, can be delayed under heavy load, and are automatically disabled in public repos after 60 days without activity, per GitHub's docs.
In practice, if you had a dozen 15-minute crons on a free Val Town account, neither Cloudflare Free (5 triggers) nor Vercel Hobby (daily only) covers you as is. You can either pay for a plan or merge several jobs into one trigger that dispatches by schedule. Merging is usually the cheaper fix. The Startup Runway Calculator can show what the new monthly bills do to a side project's budget.
Rebuild instead of re-host
Some vals are really small apps: a form, a dashboard, a personal tool. For these, the Val Town docs also list vibe-coding platforms (Lovable, Replit, v0) as rebuild options. These platforms mostly use Postgres through Supabase or Neon, so it's a rewrite, not a lift-and-shift. You can compare current options in the AI coding assistants directory.
Step 3: Move the code off esm.town
Val Town's GitHub export guide treats Git as the source of truth from now on. The steps that matter:
- Create a repo with matching visibility. If you're unsure, make it private.
- Copy the val and every val it imports, replacing
esm.townimports with local files. If you skip this, your code breaks on January 10 even if it's hosted somewhere else. - Add
.gitignorerules before the first commit. A file ignored later stays in Git history. - Commit a lockfile and deploy config for the new runtime. Put env var names in the README and the values in the provider's secret store.
- Push to a non-production branch first if the repo auto-deploys.
Some Val Town helpers have no direct equivalent. std/utils.httpEndpoint and std/utils.emailAddress become explicit configuration, imports move into package.json, and file utilities become Node-style fs calls, according to the Cloudflare mapping in the docs.
Step 4: Export SQLite and blob data correctly
Data is where migrations lose records. Val Town's guides for SQLite and blobs both use a temporary, bearer-token-protected HTTP val that streams data to a local script. The details worth copying:
SQLite
- Pause writes during the export, save the SQL dump outside Git, and record row counts for each table.
- The exporter rejects virtual tables. If you use full-text search (FTS), plan to rebuild those indexes.
- Before importing anywhere, test the dump locally:
sqlite3 -bail app.db < app.sql
sqlite3 app.db "PRAGMA integrity_check; PRAGMA foreign_key_check;"
- Turso is the path with the fewest changes. The guide creates the database from the tested file with
turso db createand the--from-file ./app.dbflag (for example,turso db create app-db --from-file ./app.db). If you connect with@libsql/clientandintMode: "string", integers come back as strings, so don't convert large IDs to JavaScript numbers. - Treat the first import as a rehearsal. At cutover, stop writes and jobs, then take a fresh full export. A stale rehearsal copy won't include later deletions.
Blobs
- List every key with pagination, and don't trust a truncated listing.
- Only bytes get copied. Blob metadata doesn't transfer, so store it in a database or a JSON sidecar.
- Check each copy with SHA-256 hashes, not ETags, and compare keys and sizes against the source list.
- Delete the temporary export val, its token, and any local export files when you're done.
SQLite and blobs stay writable after December 10, so live apps can keep collecting data during the freeze. That also means your final export has to happen as close to cutover as possible.
Step 5: Set redirects before December 10
The redirects guide affects every val.run URL that anyone outside your account uses:
- You can point any
*.val.runURL at a new location. Path and query string carry over by default, sobloggy.val.run/hello-world?ref=homebecomesexample.com/hello-world?ref=home. - You can add and edit redirects until December 10, 2026. On that date, any existing redirects become permanent. Miss the date and that URL has no forwarding.
- Once a redirect is set, the val stops receiving requests. Set it only after the new deployment is verified and the data is synced.
- Many webhooks don't follow redirects. Update the URLs in Stripe, GitHub, Slack, and similar dashboards directly.
- Redirects cover only
.val.runhostnames. Custom domains need DNS changes at your registrar.
You can set redirects per val in its HTTP settings, account-wide under Custom Domains → Val.run redirects, or by asking Townie or an MCP-connected agent.
What to do now
- This week: inventory your vals, export all code to Git, and list every webhook that points at
val.run. - By late November: deploy to the new host, rehearse the SQLite and blob imports, and fix whatever breaks without Val Town's helpers. Leave room before the freeze for that last round of fixes.
- Before December 10: cut over, update webhooks, and set redirects. After this date, code changes and new redirects are off the table.
- Before January 10, 2027: take a final data export, verify counts and hashes, and remove temporary export endpoints and tokens.
- Watch: what the February 1, 2027 open-source release actually includes, and how the Deno runtime's end of support in October 2027 affects any Deno code you moved elsewhere.
There's also a broader lesson for anyone building on small hosted platforms. Keep your code in a Git repo you control, avoid importing code by URL from the host, and know how you'd export your data before you need to. If you're launching a tool that helps developers move off Val Town or Deno, you can list it for free on LaunchBoosts.
Frequently asked questions
When does Val Town shut down?
All Val Town services end on January 10, 2027. Code becomes read-only on December 10, 2026, but SQLite and blob storage stay writable until the final shutdown. New signups and plan upgrades stopped on November 10, 2026, when the wind-down was announced.
Will my val.run URLs keep working after Val Town shuts down?
Only if you set up redirects. Val Town lets you redirect each val.run URL to a new host, and redirects you set before December 10, 2026 become permanent on that date. After December 10 you can't add or change them. Webhooks often don't follow redirects, so update those URLs directly with each provider.
Do I get a refund for my Val Town subscription?
Billing was paused on November 10, 2026, and existing subscriptions keep running for free until the shutdown. Anyone who prepaid for an annual plan will get a partial refund. The announcement doesn't explain how the refund amount is calculated, so ask support@val.town if you need the details.
What is the best Val Town alternative?
Val Town's own docs say Cloudflare matches its features most closely: Workers for HTTP, D1 for SQLite, R2 for blobs, Cron Triggers, and built-in Email Routing. Vercel and Netlify also work, but you'll need outside services for email and SQLite, such as Resend and Turso. Small personal cron scripts can move to GitHub Actions instead.
Is Val Town going open source?
Yes. The announcement says Val Town will be open-sourced on February 1, 2027. It doesn't say which components will be released or under what license, so don't plan on self-hosting it to keep production vals running.
Sources
- Val Town is winding down (official announcement)— blog.val.town
- Val Town Docs: Migrating off Val Town— docs.val.town
- Val Town Docs: Where to migrate— docs.val.town
- Val Town Docs: Export to GitHub— docs.val.town
- Val Town Docs: val.run redirects— docs.val.town
- Val Town Docs: Migrate SQLite (Vercel guide)— docs.val.town
- Val Town Docs: Migrate blobs (Vercel guide)— docs.val.town
- RuntimeWire: Val Town is winding down after four years— runtimewire.com
- Cloudflare Blog: Deno is joining Cloudflare— blog.cloudflare.com
- Cloudflare Workers platform limits— developers.cloudflare.com
- Vercel Cron Jobs usage and pricing— vercel.com
- GitHub Docs: Events that trigger workflows— docs.github.com
