What I Needed to Solve
I had a .NET console application that was originally running on a server. When the target moved to PaaS, that model no longer fit because there was no server to host the process in the old way.
- The app needed to keep running as a background process.
- The old server-based model no longer made sense in a managed PaaS world.
- I needed a cost-aware replacement that still behaved like the original job.
Why the Server Model Failed
The console app expected a server, local disk, and a place where it could run on demand or on a schedule. In PaaS, that assumption breaks quickly because the platform is not meant for you to manage a machine directly.
| Old IaaS Expectation | Why It Failed in PaaS | What I Needed Instead |
|---|---|---|
| Long-running server process | PaaS abstracts the host | Hosted job runner |
| Local file system for work files | Local disk is not durable | Blob Storage |
| Manual machine access | Not the PaaS operating model | Platform-managed execution |
Easy Migration Steps
I broke the migration into small pieces so I could prove each step before I changed the runtime model.
- Identify what the console app actually does: input, processing, file output, and downstream handoff.
- Remove local disk assumptions and move persistent files to Blob Storage.
- Host the app in a WebJob so it runs inside App Service instead of a VM.
- Move configuration into App Service settings and connection strings.
- Validate the output in Blob Storage before replacing the old server-based run path.
Why I Chose WebJobs
Azure Functions was available, but for this workload it was not the best fit. The app behaved like a background job, and WebJobs matched that shape without making the cost or runtime model more complicated than it needed to be.
- The app behaved more like a background job than an event-driven function.
- I did not need the extra abstraction or pricing overhead for this case.
- WebJobs let me keep the app model close to the original console app shape.
Target Architecture
The migration path is simple: the platform hosts the job, the job runs the console logic, Blob Storage holds the durable state, and the downstream process reads the result.
Blob Storage Replaced Local Disk
Local files were the first thing I moved out of the app. Anything that needed to survive beyond the runtime had to go to Blob Storage instead of local disk.
- The console app writes its working files to Blob Storage.
- The WebJob picks up the files or creates them directly in Blob.
- Any downstream consumer reads from Blob instead of the old server path.
Implementation
The code did not need a rewrite. What changed was the host, the storage path, and the way the job was triggered.
public static async Task Main(string[] args)
{
var blobService = new BlobServiceClient(Environment.GetEnvironmentVariable("AZURE_STORAGE_CONNECTION_STRING"));
var container = blobService.GetBlobContainerClient("work-items");
await container.CreateIfNotExistsAsync();
// Read input, process it, and write results to Blob Storage
var result = ProcessWork();
var blob = container.GetBlobClient($"output/{DateTime.UtcNow:yyyyMMddHHmmss}.json");
await blob.UploadAsync(BinaryData.FromString(result), overwrite: true);
}
Runtime Model
The job was hosted as a WebJob in App Service, which gave me a managed execution environment without maintaining the underlying server.
| Part | Role |
|---|---|
| WebJob | Runs the console app in PaaS |
| Blob Storage | Stores files and job output |
| App Service | Hosts the job without a VM |
| Configuration | Connection strings and runtime settings |
Execution Flow
The app was scheduled or started in the way the business needed, but the important part was that the execution no longer depended on a server I had to manage.
- App Service runs the WebJob.
- The WebJob executes the console logic.
- Blob Storage holds the file state.
- The workflow stays PaaS-aligned and supportable.
What I Verified
| Check | What It Proved |
|---|---|
| Blob output exists | The job completed and wrote results. |
| WebJob status is healthy | The platform is running the job. |
| Downstream consumer reads from Blob | The old server dependency is gone. |
| No local disk dependency remains | The app is suitable for PaaS. |
What Happened In Practice
The hardest part was not the code. It was removing the assumption that the app needed a server sitting there waiting for it. Once the job moved into WebJobs and the files moved into Blob Storage, the application behaved like a managed cloud workload instead of a server-bound process.
Delivery Lessons
- When you move from IaaS to PaaS, the execution model usually needs to change too.
- Blob Storage is the right replacement when local files are part of the app’s state.
- WebJobs fit background console workloads well when Functions is not the right cost or shape.
- The best migration is the one that removes server dependence without overcomplicating the app.