All posts
Joe Connolly free plan, hosting, scale to zero

Free web app hosting, and how we can afford it

One web app in any language, hosted free with no card and no time limit. Here's how it works, the catch, and what the Free plan isn't for.

Free web app hosting, and how we can afford it

If you had a side project on Heroku in 2022, you probably remember the email. Free dynos were going away that November, and every little app that had been quietly running for years suddenly needed a credit card or a new home.

Free plans have a habit of ending like that. An app that runs around the clock costs its host about the same whether it's free or paid, and the typical free app spends most of its life with nobody using it. It's a bill for an empty room, and eventually somebody stops paying it.

When we added free web app hosting to velixir, I wanted a plan we'd never have to take back. That meant it had to cost us almost nothing whenever nobody was using it, and most of what follows comes from that one decision.

How the Free plan stays free

A free app on velixir is a normal app with one difference. After 15 minutes without a request, we scale it to zero. The container stops and nothing of yours is using CPU or memory, while your code, your settings and your address stay exactly where they were.

The address keeps working, too. Every request to a velixir app passes through our edge first, the layer that handles HTTPS and routing. When a request turns up for an app that's asleep, the edge starts the app, waits for it, and then hands the request over. From then on the app runs as normal until it has another quiet 15 minutes.

A sleeping app costs us a row in a database, a route on the edge and its image in our registry. That's close enough to nothing that we can give it away with no end date. It isn't a trial, and nothing is counting down. If you forget about it for a year, it doesn't turn into a bill.

What you get

Free plan
Price €0, no time limit
Apps One free app per account
CPU and memory 0.25 vCPU, 256 MB
Disk 1 GB of scratch space
Goes to sleep After 15 minutes without a request
Address your-app.velixir.run with HTTPS, or your own domain with a free certificate
Traffic No per-GB charges, outbound capped at 10 Mbit/s
Card Not needed

It's a whole backend, not a function or a static site. Push source code in any language we run (Node.js, Python, Go, Ruby, PHP, Java, Elixir, Rust, .NET or Deno) and velixir builds it for you. You can deploy from the command line, from a GitHub Actions workflow, from a public GitHub repo, or by picking one of the templates.

Most of what paid apps get comes with it: environment variables and secrets, live logs, rolling back to any earlier release, and the Security tab with rate limiting, a web application firewall and an under-attack mode. Free apps run on the same servers in the EU as paid ones, behind the same edge. What you don't get is room to grow. There are no extra replicas, no autoscaling, no high availability and no staging slots.

The catch is the cold start

Free hosting always has a catch, and ours is the first request after a nap. When your app has been asleep, that request has to wait while it starts up.

How long that takes is mostly down to your app. A small Node.js, Go or Python server is usually up in a few seconds. A framework that does a lot of work at startup takes longer, and it's doing that work on at most a quarter of a CPU, so if something takes ten seconds to boot on your laptop, expect it to take longer here.

What people see while they wait depends on who's asking:

  • Someone in a browser gets a small "Waking up" page after three seconds. It reloads itself as soon as your app answers, so they end up on your page rather than an error.
  • API clients and webhooks don't get a page. The edge holds their request for up to 28 seconds while the app starts, then passes it through. If the app still isn't up by then, they get a 503 with a Retry-After header.

blog-free-wake-page

That waking page says, at the bottom, that the app is hosted on velixir's free plan. It's the only place we put our name. Your own pages reach visitors exactly as your app sends them, with nothing added.

One setting makes the wait more reliable. By default an app counts as started as soon as its container is running, even if it needs another second or two before it's listening, and a request that lands in that gap can get an error instead of your app. Turn on the HTTP health probe on the app's Scaling tab, under Runtime, and point it at a path your app answers (/health unless you change it). Then we wait until your app actually responds before sending anyone in. It also stops a broken deploy from going live, which is reason enough on its own.

What a free app is good for

Anything that gets used in bursts and can forgive a slow first request. That turns out to be a lot of things:

  • a portfolio or personal site that needs a real backend, not just static files
  • the API behind a side project, a hackathon entry or a prototype you want people to try
  • a small internal tool your team opens a few times a day
  • a Telegram bot, which receives messages as webhooks and can sleep in between
  • a remote MCP server that gives Claude Code or Cursor access to your own tools
  • learning how deployment works, without a bill arriving while you work it out

The Telegram bot and the MCP server are both templates, alongside a starter app for every language we run. Most of the templates fit on the Free plan, and the ones that can will pick it by default.

What it isn't for

Because it sleeps, anything that has to stay awake doesn't belong on the Free plan:

  • Discord bots, and anything else that holds a connection open waiting for something to happen.
  • Background workers, queues and scheduled jobs. While the app is asleep nothing in it runs, including timers and cron libraries inside your own code.
  • Webhook receivers with a tight timeout, where a slow first reply counts as a failure.
  • Checkout, sign-in, or anywhere else that a few seconds of waiting costs you a customer.

The templates already know this. The ones that have to stay awake, like the Discord bot, the background job queue and n8n, won't let you pick the Free plan at all.

Two limits apply even while it's awake. The disk is scratch space, so anything your app writes to its own filesystem is gone when it sleeps or redeploys. Keep what matters in a database, in Valkey or in object storage. And it's one copy of your app on up to a quarter of a CPU, with outbound traffic capped at 10 Mbit/s. That's plenty for a side project. If you're hoping to end up on the front page of Hacker News, move to a paid plan first.

The full list is in limits and fair use.

Do I need a credit card?

No. You can sign up, deploy and keep a free app running without ever adding one.

Anything that costs money comes out of credit, and every new account gets €3.49 of it with no card, valid for 30 days. That's enough to try a paid plan or a small database for a few weeks. A card comes in when you want more than that: topping up, running more than one app, or swapping the starter credit for the €14.99 we give you the first time you add one.

If your free app needs a database, managed Postgres starts at €4.95 a month and Valkey at €2.45, both billed by the hour, and the app itself stays free. Attach one and its connection string appears in your app as an environment variable, DATABASE_URL for Postgres or REDIS_URL for Valkey.

Once there's something paid on the account, though, normal billing applies to all of it. If the credit runs out and isn't topped up, we email you first, and if it's still unpaid the account is paused, free app included. The billing docs have the exact timeline. A free app on its own never gets anywhere near this, because it never costs anything.

When it's time to pay

If your app turns into something people rely on, the cold start is usually the first thing you'll want gone. The Hobby plan is €3.49 a month. It never sleeps, and it doubles the CPU and memory to 0.5 vCPU and 512 MB. It's billed by the hour like everything else, so you can try it for a few days and pay for those days.

You change plan from the app's Scaling tab. The app keeps its address, domains, environment variables and database. It stops sleeping straight away, and the extra CPU and memory apply from your next deploy. Everything bigger is on the pricing page.

If you'd rather keep it free, keep it free. We don't delete free apps for being quiet. If yours sleeps for a whole month, I'll send you one email to say it's still there, and that's all.

Try it

The quickest way to see it working is a template. The starter apps for each language are live in about a minute. Or bring your own code, by pasting a public GitHub repo at velixir.net/new or running velixir deploy in your project folder. If you want the short version to send to someone, it's on the free web app hosting page.

If the Free plan gets in your way somewhere I haven't covered, open a ticket and tell me. I'd rather fix the plan than have you quietly leave.


Got an app to ship? velixir hosts it in any language, on servers in the EU.

Start free - your first month's on us