All posts
Joe Connolly launch, .net, getting-started

Deploying your first .NET app to velixir

From an ASP.NET Core app on your laptop to live in your chosen region in fifteen minutes, with no Dockerfile and no YAML. A walkthrough of velixir's apps, managed Postgres, and managed Valkey, written by the founder.

Deploying your first .NET app to velixir

After ten years of writing C# I've used most of the major .NET hosting options. Azure App Service for the day jobs, Heroku for side projects, Render here and there. The frustration was always the same shape, just dressed up differently each time.

Hello World. This is the first post on the velixir blog. If you're considering a move from one of those platforms, this post explains why velixir exists, what it looks like to deploy your first app, and what the managed database and cache side of the platform does.

What I was tired of paying for

The most consistent complaint with the major PaaS options is the spend-to-resource ratio. Azure App Service's smallest production tier is a 1-core, 1.75 GB box for around $13 a month. Fine for a hobby. The moment you need autoscaling you're forced into Standard at $73 a month for hardware identical to the lower tier. Autoscaling and deployment slots are the paywall, not the silicon.

The portal earns the bill in volume rather than usefulness. Wiring up a custom domain crosses four separate blades. Logs are split across four different surfaces showing overlapping subsets of what you actually want. Setting up basic monitoring on App Service shouldn't feel like an integration project.

Application-layer DDoS protection isn't included. The default network-layer protection catches volumetric flood attacks but does nothing about an attacker hammering your /api/heavy-query endpoint with valid-looking HTTP. Application-layer protection on Azure means upgrading to Front Door Premium or DDoS Protection Standard at $2,944 a month. Most apps in the wild run without app-layer protection because nobody on a normal budget pays three grand a month for it.

Heroku has the same shape in different packaging. The Standard 1X tier is $25 a month for 512 MB. Managed Postgres and Redis live behind their own billing pages with their own pricing curves. The free tier disappeared in 2022. Lower-tier dynos cold-start. Render is closer to what I wanted, but it defaults to US regions and .NET support means either a Dockerfile in your repo or a generic runtime that lags behind .NET majors.

I built velixir because I'd run out of patience paying enterprise prices for platforms that still expect me to know what an App Service Plan is, where my logs ended up this time, or why nothing in the dashboard is in euros. The platform is a year of trying to fix all of that at once. Here's what the result looks like.

The five-minute story

This is what deploying a brand new app looks like end to end.

Step one. Sign up. Visit velixir.net/account/register. Thirty seconds. Email confirmation lands instantly. We don't require a credit card at sign-up, so you can browse around. A payment method only gets attached when you're ready to provision your first paid resource.

Step two. Create the app. Click Create App in the dashboard, pick a plan (Spark at €6.95/mo is fine for a side project), pick a region (Europe, US East, or Asia Pacific), and pick a .NET version. The default is whichever LTS Microsoft is currently shipping.

Step three. Connect your code. Two options. If your code lives in a Git host, paste the repo URL and the next push to your chosen branch triggers a build. If you'd rather control deploys from your terminal, run:

dotnet publish -c Release
velixir push --slug your-app-name

The CLI picks up your publish output, ships it to our build pipeline, and rolls it out across replicas. Most apps go from "git push" to "serving traffic" in around ninety seconds.

Step four. There is no step four. Your app is live at https://your-app-name-{region}.velixir.run with a working TLS certificate. Point a custom domain at it whenever you're ready.

What's actually happening behind the scenes

The thing I care about most with velixir is that the platform is built around the actual .NET toolchain instead of around a generic container abstraction. The first time you push, we invoke the official .NET SDK with the same flags you'd use locally. We don't transcode your project into anything else. There's no buildpack in the middle pretending to understand .NET project structure. If dotnet publish works on your machine, it works on velixir.

The result is a release artifact: your publish output stored durably. Each push creates a new release. Each release sticks around for the lifetime of your account. Rolling back is a one-click operation that points traffic at a previous artifact, so it happens in seconds and can't fail in any of the interesting ways re-running a build can fail.

Once the artifact is built, we deploy it across the region you chose. Each app gets its own isolated workload, its own internal endpoints, and its own routes through our global edge layer. You see an app, replicas, deploy history, logs, and metrics. The orchestration substrate stays out of your way.

Traffic into your app passes through our edge layer before it touches your replicas. Application-layer DDoS protection is on by default for every app. No add-on, no separate billing line, no premium tier to upgrade to.

The autoscaler is tuned specifically for .NET workloads. Off-the-shelf autoscalers wait five minutes for a fresh replica's CPU metrics to "stabilise" before factoring them into scale decisions. That window is reasonable for shared multi-tenant clusters with weird workloads. For a managed PaaS where every customer's autoscaler is independent, it's overkill. We dropped it to one minute. When traffic spikes, fresh replicas show up in scale decisions about four minutes earlier than they would with default tuning.

Managed Postgres, because everything needs a database

Almost every app I've written needs a database. On most PaaS providers you pick a Postgres add-on, the pricing is opaque and structured to scale to "enterprise" before you realise it, and you copy a connection string between two consoles every time you provision a new environment.

velixir's managed Postgres is a first-party service with four tiers, all priced hourly in euros. Hobby starts at €4.95/mo: 0.25 vCPU, 512 MB of RAM, 5 GB of storage, and a seven-day point-in-time-recovery window. Right for side projects and dev environments. Standard at €17.95/mo bumps you to 1 vCPU, 2 GB of RAM, 20 GB of storage, a 30-day PITR window, and optional HA. The default choice for production. Pro at €64.95/mo gets you 2 vCPU, 8 GB of RAM, 100 GB of storage, 90-day PITR, HA included, and one read replica. Scale at €169.95/mo is 4 vCPU, 16 GB of RAM, 500 GB of storage, three read replicas, and cross-region backup baked in.

Provisioning works the same way as apps. Click Create Database, pick a plan, a region, a Postgres version (17, 16, or 15), and a name. The instance comes up in about a minute. You can connect from psql or your migration tool if you flip on external access, but the more interesting workflow is linking the database to an app from the dashboard. When you link, we inject DATABASE_URL into the app's environment as a standard libpq connection string. Your code reads it and gets on with life:

var conn = Environment.GetEnvironmentVariable("DATABASE_URL");
services.AddDbContext<AppDbContext>(o => o.UseNpgsql(conn));

No credentials in source control. No copy-pasting between dashboards. Rotate the connection and we re-inject the new value on the next deploy.

Every instance ships with a connection pooler in front, so an Npgsql connection storm during a deploy doesn't blow your max_connections. Point-in-time recovery uses continuous WAL shipping, so the seven-day window on Hobby is a real seven days. You can restore to any second within it.

Managed Valkey for the things that shouldn't hit your database

The other piece of infrastructure most apps need is a cache. We ship Valkey for that role: an open-source, BSD-licensed cache that's wire-compatible with everything you've ever written against the Redis protocol.

In practice this means StackExchange.Redis works without changes. Existing tooling works. Existing dashboards work. We run it as a fully-managed service with snapshots, optional persistence (RDB plus AOF on Standard and above), and an optional sync replica for HA.

Four tiers on the same hourly-EUR model. Hobby at €2.45/mo runs 0.1 vCPU and 256 MB of RAM, ephemeral, which is the right shape for session state in a single-region app. Standard at €8.95/mo bumps you to 0.5 vCPU and 1 GB of RAM with RDB + AOF persistence, optional HA, and a 7-day snapshot window. Pro at €26.95/mo is 1 vCPU and 4 GB of RAM with 14-day snapshots. Scale at €89.95/mo is 2 vCPU and 16 GB of RAM for cache-heavy workloads, with 30-day snapshot retention.

Linking works exactly the same way as databases. Click link, pick the cache, and REDIS_URL shows up in your app's environment.

using var muxer = ConnectionMultiplexer.Connect(
    Environment.GetEnvironmentVariable("REDIS_URL"));

Where velixir runs

velixir has compute regions in Europe, US East, and Asia Pacific. Pick a region per app, per database, per cache. Cross-region warm-standby HA is a one-toggle option on any plan: a second replica in a different region, sub-second failover via DNS health checks if your primary goes dark.

We bill in euros across every region. The pricing on the page is the pricing on your invoice. No FX surprises, no padded conversion margins, no different price list per region.

What's shipping today

You can deploy ASP.NET Core APIs, MVC apps, Blazor Server apps, gRPC services, background workers, and any other .NET workload that publishes via dotnet publish. Every major .NET version since Core 1.0 is runnable. The actively-supported ones get Microsoft's security patches automatically.

We support custom domains with automatic TLS certificates, environment variables (encrypted at rest), real-time log streaming, runtime metrics, autoscaling, cross-region warm-standby HA, atomic rollback, and deploy slots for blue-green or preview environments. Application-layer DDoS protection is on by default for every app. The CLI works on Windows, macOS, and Linux.

I'm genuinely open to feedback. If something doesn't work quite right, or you've got an opinion on how a feature should behave, email me at [email protected] (I read everything) or open a support ticket from the dashboard. velixir exists because I was tired of paying enterprise prices for hosting that didn't quite fit the .NET shape, and I'd rather hear what's missing from you directly than have you quietly switch back to Azure.

The trial

The first month is on me, up to €14.99 of credit. That's enough to run a Spark app, a Hobby database, and a Hobby cache for the full month with a bit of headroom left. The credit lands the moment you add a payment method, you spend it down at the same hourly rates as paid usage, and if you don't burn through it in the first thirty days it expires. We don't extend it. We don't chase you for the difference. We don't retro-bill you.

Sign up at velixir.net, spend fifteen minutes, deploy something. If it doesn't work, tell me what broke and I'll fix it.

Joe Founder, velixir


Liked this post? velixir is hiring its first .NET customers.

Start free - your first month's on us