Azure Functions for .NET Developers — Series 1, Part 1
You've just finished building a webhook handler. Maybe fifty lines of code—parse some JSON, hit a database, return a response. Now comes the fun part: provisioning a VM, configuring IIS, setting up SSL certificates, writing health checks, and figuring out how to scale when traffic spikes at 3 AM. Sound familiar?
This is the problem serverless computing solves. Instead of managing infrastructure, you write the code that matters—your business logic—and let the platform handle everything else. In 2026, with cloud costs under constant scrutiny, the pay-per-execution model makes even more sense: why pay for idle servers when you can pay only for the milliseconds your code actually runs?
For .NET developers, Azure Functions has matured into a first-class serverless platform. The isolated worker model, combined with .NET 10's performance improvements, means you get the full power of modern .NET without compromise.
Every major cloud provider offers a serverless compute platform—AWS has Lambda, Google Cloud has Cloud Functions. For .NET developers, Azure Functions is the most natural choice: first-class support in the .NET SDK, seamless integration with Visual Studio and Rider, and deep ties to the broader Azure ecosystem you're likely already using. If your team runs on .NET, you won't fight the tooling here.
In this series, we'll explore Azure Functions from the ground up—when to use them, how they work, and the patterns that make serverless development practical. Let's start with the fundamentals.
What Azure Functions Actually Is
Azure Functions is Microsoft's event-driven serverless compute service. Instead of managing servers or worrying about infrastructure, you write small, focused pieces of code that run in response to events. Azure handles scaling, patching, and availability automatically.
Triggers: What Starts Your Code
A trigger defines what event causes your function to execute. Common triggers include:
- HTTP Trigger - Respond to web requests (APIs, webhooks)
- Timer Trigger - Run on a schedule (cron expressions)
- Service Bus Trigger - Process messages from queues or topics
- Cosmos DB Trigger - React to document changes in your database
- Blob Trigger - Execute when files are uploaded to storage
Bindings: Declaring Inputs and Outputs
Bindings connect your function to other Azure services declaratively. Instead of writing SDK code to read from a queue or write to a database, you declare the connection through attributes—and Azure Functions handles the plumbing.
There are two types:
- Input bindings - Read data when your function executes (e.g., fetch a document from Cosmos DB, read a blob from storage)
- Output bindings - Write data after your function completes (e.g., add a message to a queue, insert a row into Table Storage)
Your function's return value can serve as an output binding directly. Return an object, and Azure Functions writes it to the configured destination—no explicit SDK calls needed.
Your First Function
Here's a minimal HTTP-triggered function using the .NET 10 isolated worker model:
public class HelloFunction(ILogger<HelloFunction> logger)
{
[Function("Hello")]
public IActionResult Run([HttpTrigger(AuthorizationLevel.Function, "get")] HttpRequest req)
{
logger.LogInformation("Processing request");
return new OkObjectResult("Hello from Azure Functions!");
}
}
The [HttpTrigger] attribute defines this as an HTTP GET endpoint with function-level authentication (we'll cover authentication levels in the next article). The OkObjectResult you return becomes the HTTP response sent back to the caller—Azure Functions maps ASP.NET Core's familiar result types to actual HTTP responses for you. That's all you need to deploy a working API endpoint.
When to Use Azure Functions (and When Not To)
Azure Functions excels in specific scenarios, but it's not a universal solution. Here's an honest breakdown to help you choose wisely.
Where Functions Shine
APIs with unpredictable traffic. If your endpoint gets 100 requests one hour and 10,000 the next, you pay only for what you use. No idle VMs burning budget overnight.
Event-driven workloads. Processing messages from Service Bus, reacting to blob uploads, or handling Event Grid notifications—Functions integrates natively with Azure's eventing ecosystem. A few lines of code and you're processing events at scale.
Scheduled jobs. Timer triggers replace fragile cron servers. Need to clean up stale data every night or send weekly reports? Functions handles the scheduling infrastructure for you.
Glue code between services. Moving data from one system to another, transforming payloads, or orchestrating simple workflows—Functions keeps these small integrations from becoming maintenance burdens.
Prototypes and MVPs. When validating an idea quickly, Functions lets you ship without configuring infrastructure. You can always migrate to containers later.
When to Look Elsewhere
Latency-critical paths. Cold starts on the Consumption plan can add seconds of delay. If you need consistent sub-10ms response times, consider App Service or Container Apps with always-on instances.
Long-running processes. The 10-minute timeout (or 230 seconds on HTTP triggers) won't work for heavy batch processing. Look at Durable Functions for orchestration or Container Apps Jobs for extended compute.
Heavy, sustained compute. If you're running CPU-intensive workloads continuously, reserved container instances often cost less than millions of function executions.
Stateful applications. WebSocket connections, in-memory caches, or persistent sessions don't fit the ephemeral Functions model.
A Note on Cost Protection
Pay-per-execution pricing has a flip side: you pay for every request, including malicious ones. A DDoS attack against an unprotected Function endpoint means you're footing the bill for traffic you never wanted.
For public-facing APIs, consider these safeguards:
- Azure API Management — rate limiting, throttling, and request quotas
- Azure Front Door or Application Gateway — WAF rules and DDoS protection
-
Function authorization levels —
AuthorizationLevel.FunctionorAuthorizationLevel.Adminrequire keys, blocking anonymous traffic
The Consumption plan's cost model works best when you control who can call your endpoints. For truly public APIs expecting untrusted traffic, budget for a protection layer—or consider the Premium plan's predictable pricing.
Quick Comparison: Functions vs App Service vs Container Apps
Choosing the right Azure compute option can significantly impact your costs and application architecture. Here's how Azure Functions stacks up against the other popular choices for .NET workloads:
| Feature | Azure Functions | App Service | Container Apps |
|---|---|---|---|
| Scale trigger | Events (HTTP, queue, timer) | CPU/memory rules | Events (KEDA), CPU/memory |
| Pricing | Pay-per-execution* | Fixed/reserved | Per-resource (vCPU/memory) |
| Cold starts | Yes (Consumption) | No | Configurable |
| Scale-out limit | 200 (Consumption) / 1,000 (Flex) | Up to 30 instances | 300–1,000 replicas |
| Best for | Event-driven, APIs | Web apps, APIs | Microservices |
*Consumption plan. Premium and Dedicated plans use fixed or memory/CPU-based pricing, similar to Container Apps.
Choose Azure Functions when you have event-driven workloads, sporadic traffic patterns, or want to minimize costs for low-volume APIs. Opt for App Service when you need predictable performance without cold starts for traditional web applications. Consider Container Apps when building microservices architectures that require more control over the runtime environment while still benefiting from managed scaling.
A Note on .NET 10
Throughout this series, we'll use .NET 10 with the isolated worker model—the recommended stack for new Azure Functions projects. It's an LTS release (supported through November 2028) and gives you full ASP.NET Core integration with familiar types like HttpRequest and IActionResult. We'll cover the setup in Part 2 and what "isolated worker model" means in detail in Part 5.
What's Next in This Series
This article covered the "why" of Azure Functions—now it's time for the "how." Over the next several parts, we'll build real-world skills you can apply immediately.
Part 2: Your First Azure Function with .NET 10 (coming soon) walks through project creation, running locally, and testing with curl. You'll have a working HTTP endpoint in minutes.
Part 3: Beyond HTTP Triggers (coming soon) explores timer, queue, and blob triggers—the event-driven patterns that make Functions powerful.
Part 4: Local Development Setup (coming soon) covers the tools, debugging techniques, and productivity tips that make daily development smooth.
Part 5: Understanding the Isolated Worker Model (coming soon) explains the architecture behind modern Azure Functions—why Microsoft created it, how it works, and what it means for your code.
Conclusion
Azure Functions has become a practical choice for .NET developers who want to ship features without managing infrastructure. The isolated worker model with .NET 10 gives you modern language features, familiar patterns, and genuine pay-per-use economics.
Start small. Create an HTTP-triggered function, deploy it to Azure, and see how quickly you can go from code to production. The barrier to entry has never been lower.
Follow this series to build your serverless skills step by step. Next up: setting up your development environment and deploying your first function. Let's build something.
Top comments (0)