Managed hosting for .NET applications, run the way we run our own. Publish a build, watch it pass its health checks, and let it take traffic — without maintaining a single Linux box or writing another systemd unit.
How it works
How a build reaches production, who owns the runtime underneath it, and what happens on the day traffic is not what you sized for. Everything else is in the spec table.
Rollouts
A publish starts the new build beside the running one and waits for its health endpoint. Only then does traffic move, and only then is the old instance drained. If the health check never passes, the rollout is abandoned and your users never knew there was one.
$ dotnet publish -c Release$ intrvll deploy ./bin/Release/net10.0/publish uploading 18.4 MBstarting v87 (v86 still serving)health GET /health/ready 503health GET /health/ready 200traffic v86 -> v87drain v86 stopped (0 in flight) live in 24.8s - 0 failed requests
Runtime
.NET security and patch releases land on our schedule without a migration project on yours. The major version is yours to choose per app, so 10 LTS stays 10 LTS until you say otherwise, and Kestrel sits behind our proxy with HTTP/3 and WebSockets already terminated correctly.
{ "runtime": "dotnet:10-lts", "entrypoint": "Astrava.Api.dll", "health": "/health/ready", "websockets": true, "sticky": true // SignalR "env": { "ConnectionStrings__Default": "@postgres.url" }}
Dynamic plan
Fixed plans are the honest default when load is flat. When it is not, the Dynamic plan puts a permanent 1 GB and 1 vCPU under the app for a flat €10 and grants whatever it asks for above that, billed by the hour and only while in use.
floor 1 GB / 1 vCPU €10.00 flat 08:00-17:00 at floor17:12-17:58 2.8 GB / 2 vCPU 0h 46m18:00-23:59 at floor metered above floor 0h 46mceiling 8 GB not reached
Getting started
A framework-dependent publish is all we need. No container to build, no Dockerfile to maintain.
dotnet publish -c ReleaseRuntime, entrypoint and health endpoint. Everything else has a sane default you can override later.
runtime: dotnet:10-ltsThe same deploy command runs from a GitLab or GitHub job, so merges to your release branch ship themselves.
intrvll deploy ./publishHealth check, traffic shift, drain. If any of it fails the previous version is still the one serving.
Fixed plans give you a known number on the invoice. Dynamic gives you a floor and lets the app take what it needs above it. Either way there is no separate charge for deploys, builds, health checks or seats, and changes are prorated to the day.
The base covers 1 GB of RAM and 1 vCPU, always yours. When the app needs more than that it simply gets more — no throttling, no resize window, no support ticket — and the extra is billed per GB-hour and per vCPU-hour, the way pay-as-you-go compute works at the hyperscalers. The difference is that the floor is €10 rather than a per-second bill for everything, so a quiet month stays a quiet invoice.
Specifications
Everything the platform does that did not need a paragraph above. If something you need is missing from this list, it is missing from the product.
Before you buy
No. You hand us the output of dotnet publish and we run it. There is no Dockerfile to write and no registry to keep. If you already have a container workflow you would rather keep, tell us - but nothing here requires one.
.NET 8, 9 and 10 LTS, pinned per app. Patch releases within your major are applied by us. A major upgrade never happens on its own; you move when your code is ready, not when Microsoft ships.
Yes. WebSockets are terminated correctly and sticky routing keeps a connection pinned to the instance that owns it. For more than one instance, point it at the managed Redis backplane and scale-out behaves the way the documentation says it should.
A fixed plan is cheaper when load is flat, and you should take one if it is. Dynamic is for load that spikes: the €10 floor is always there, the headroom above it is granted the moment the app asks and billed only for the hours it was used. If your busy hour is an hour, you pay for an hour rather than a month.
It is abandoned. The new instance is stopped, the old one keeps every request it was already serving, and you get the failing health response in the deploy log. Nothing about a bad build reaches a visitor.
Yes. An IHostedService inside the app runs as part of it. A separate worker process is also fine and deploys on the same cycle; give it its own app if it is heavy enough to compete with request handling.
On hardware we own, in the EU. The app, the managed PostgreSQL add-on, the logs and the backups all stay there. There is no US transfer in the path and no third-party platform underneath us.
Our own console, billing and provisioning are ASP.NET Core on this exact platform. Bring us a build and an appsettings file — we'll tell you honestly whether it fits.