.NET console apps and background services

The C# application compiles and runs your project with dotnet run on every start. Here's how the Project location and project file variables work, and the BackgroundService pattern for a worker that stays up.

The C# application is one of the few Falix runtimes that builds and runs your code on the server: on start it restores your NuGet packages and runs your project with dotnet run. That makes it a comfortable home for console apps and long-running background workers. This guide covers the two variables that point Falix at your project, and the idiomatic .NET pattern for a service that stays alive.

At a glance
You need A Falix server running the C# application
Plan Any — on free it runs while your session timer has time left, premium runs 24/7
Time Twenty minutes
New to the C# app? C#, Deno, Dart, Elixir, and Lua on Falix

What runs on start

When you press Start, the C# application does three things in order:

cd <Project location>
dotnet restore
dotnet run --project <project file>

Two variables on the Settings page (Environment tab) point it at your code, and they must match your layout exactly:

Variable Env name Default What it is
Project location PROJECT_DIR /home/container The folder Falix changes into before building
project file PROJECT_FILE (set this) Your project, e.g. MyApp.csproj

⚠️ Heads up: If Project location doesn't contain your project, or project file names something that isn't there, restore and run fail before a single line of your code executes. A misconfigured variable is the most common reason a C# server never starts.

Version: .NET 2.1 through 10 are selectable in Settings (default 8). Pick the version your project targets.

A minimal console app

A plain console program is just Program.cs:

Console.WriteLine("Hello from .NET on Falix!");

That runs, prints, and returns — and here's the catch that trips people up:

🎯 Good to know: A console Main that runs and returns exits cleanly, and the panel then shows the server as stopped. That's correct for a one-shot job. For something meant to run forever — a bot, a poller, a worker — you need code that keeps the process alive, which is exactly what a background service does.

A pure console worker makes only outbound connections, so it needs no port. If yours does serve web traffic, read Environment.GetEnvironmentVariable("SERVER_PORT") and bind 0.0.0.0 like every other runtime — see Your first web app.

The BackgroundService pattern

For a long-running worker, .NET's own answer is the Worker Service: a generic host that runs one or more BackgroundService classes and keeps the process alive until it's told to stop. Scaffold one locally with dotnet new worker, then your Program.cs and worker look like this:

using Microsoft.Extensions.Hosting;

var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<Worker>();
builder.Build().Run();

class Worker : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            Console.WriteLine($"tick at {DateTime.Now:HH:mm:ss}");
            await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
        }
    }
}

Why this is the right shape for Falix:

  • Build().Run() blocks, keeping the process alive so the server stays up instead of exiting.
  • ExecuteAsync receives a stoppingToken that's cancelled when the host shuts down. When Falix stops your server, Task.Delay is cancelled and the loop exits — a graceful shutdown, not a hard kill.
  • You get dependency injection and structured logging for free, which pays off the moment the worker grows past a loop.

Dependencies

There's no Packages page for the C# application — the dotnet restore step is your install step. Add a NuGet package by adding a PackageReference to your .csproj:

<ItemGroup>
  <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>

Restart, and dotnet restore fetches it on the next start.

💡 Tip: The first restore and build are slow — that's normal, not a hang. Later starts reuse what's already restored and built, so they're much quicker (until a reinstall wipes those folders, at which point the next start rebuilds them).

Everything past the Falix-shaped parts is standard .NET — Microsoft's documentation at learn.microsoft.com/dotnet covers Worker Services, hosting, and the framework in full.

When things go wrong

  • Couldn't find a project to run / MSBUILD errors on start — the Project location or project file variable doesn't match your layout. Fix them on the Settings page so PROJECT_DIR holds the folder and PROJECT_FILE names your .csproj.
  • Starts, then stops with no error — a console Main that returns exits cleanly and the server shows as stopped. Use the Host/BackgroundService pattern above to keep it alive. See My app won't start.
  • restore can't find a package — a PackageReference name or version is wrong. Read the dotnet restore output at the top of the console; it names the package it couldn't resolve.
  • Framework/SDK mismatch — your project targets a newer framework than the selected runtime. Bump the .NET version in Settings to match, or lower your target framework.

Next steps

Was this guide helpful?