Azure Function Apps are a serverless compute service that runs small focused pieces of C# code in response to events. You write a function, deploy it to Azure, and it runs only when triggered — paying only for the milliseconds it actually executes, not for a server sitting idle 24 hours a day.
I used Function Apps at Blue Yonder as the transformation and processing layer in our integration pipelines. Logic Apps handled orchestration, Service Bus handled messaging, and Function Apps handled the complex C# logic that was too sophisticated for Logic App expressions.
Function App vs Logic App vs API Management
This is the question every Azure engineer faces. Here is the honest answer:
Use Function Apps when you need complex C# business logic, custom data transformation algorithms, high performance compute, or reusable code components across multiple pipelines.
Use Logic Apps when you are connecting existing services visually, the workflow has clear sequential steps, or you need one of the 500+ built-in connectors.
Use API Management when exposing APIs to external consumers, applying rate limiting and authentication, or managing API versioning and documentation.
The real answer for enterprise integrations is use all three together. APIM as the front door, Logic App as the orchestrator, Function App for complex transformations, Service Bus for reliable messaging between them. This is exactly the pattern I built at Blue Yonder.
The Six Trigger Types
A trigger is what causes your function to run. Every function must have exactly one trigger.
HTTP Trigger runs when an HTTP request arrives. Use for REST APIs, webhooks, and callbacks from external systems.
Timer Trigger runs on a schedule using a CRON expression. Use for nightly jobs, hourly reports, and cleanup tasks. The expression "0 0 2 * * *" runs at 2am every day.
Service Bus Trigger runs when a message arrives on a queue or topic subscription. This was my most used trigger at Blue Yonder. It automatically handles retries and dead lettering — your function completing successfully means the message is completed, throwing an exception means it gets retried.
Blob Storage Trigger runs when a file is uploaded to Azure Blob Storage. Use for image processing, file transformation, and document parsing.
Queue Storage Trigger runs when a message arrives in an Azure Storage Queue. Good for simple high-volume task processing at the lowest cost.
Event Grid Trigger runs when an Azure event occurs — like a new user created in Azure AD or a resource deployed in your subscription. Use for reacting to platform-level events.
Input and Output Bindings
Bindings are the most underused feature of Function Apps. They connect your function to other Azure services without writing any connection boilerplate code.
An input binding reads data into your function automatically. An output binding writes data out of your function automatically. You declare what you need in the function signature and Azure handles the connections.
Instead of writing 20 lines of SQL connection code to read a record, you add one attribute to your parameter and Azure injects the data directly. Instead of writing Service Bus SDK code to send a message, you add an output binding and just call AddAsync with your object.
This eliminates entire classes of connection bugs and makes functions dramatically easier to read and test.
Durable Functions — Long Running Workflows
Regular functions run for a maximum of 10 minutes on the Consumption plan. Durable Functions solve this with a pattern that can run for hours, days, or even months.
There are three function types. The Orchestrator coordinates the workflow — calling activity functions in sequence or parallel, handling retries and timeouts, with state automatically checkpointed so it survives restarts. The Activity does the actual work — calling external APIs, querying databases, sending messages. The Client starts the workflow, usually via an HTTP trigger, and returns an instance ID for status checking.
I used Durable Functions at Blue Yonder for integration flows that needed to wait for external system responses — start the flow, call ServiceNow, wait up to 24 hours for a callback, then continue processing. Without Durable Functions this required complex custom state management. With them it was straightforward orchestration code.
Connecting to Azure Key Vault
Never hardcode connection strings in your function code. Use Key Vault references in your application settings instead.
In the Azure Portal under your Function App Configuration, add an application setting with a Key Vault reference as the value. Azure resolves the reference automatically at runtime — your code just reads the setting name as a normal environment variable. Enable Managed Identity on your Function App and grant it the Key Vault Secrets User role. No passwords anywhere in code or config files, ever.
Hosting Plans — Which to Choose
The Consumption plan charges per execution at roughly $0.20 per million calls. It auto-scales automatically but has a 10 minute timeout and 1-3 second cold starts on first call. Perfect for unpredictable traffic and low volume workloads.
The Premium plan costs around $140 per month minimum but eliminates cold starts with pre-warmed instances, has no timeout limit, and supports VNet integration. Use this for production customer-facing functions where latency matters.
The Dedicated plan runs on an existing App Service plan. Use this when you already have App Service infrastructure and want consistent predictable load without the serverless cold start behavior.
Key Lessons From Production
Always use Managed Identity and Key Vault — never hardcode connection strings anywhere.
Service Bus trigger is more reliable than HTTP for processing integration messages — it handles retries, dead lettering, and message locking automatically.
Use Durable Functions for any workflow that might run longer than 10 minutes or needs to wait for external callbacks.
Premium plan eliminates cold starts for customer-facing functions — the Consumption plan cold start is acceptable for background processing but not for real-time user requests.
Keep functions small and focused — one function should do one job. If your function is doing three things, split it into three functions.
Always add local.settings.json to your .gitignore file — it contains your local connection strings and must never be committed to GitHub.
The Complete Azure Integration Stack
This is the architecture that handles enterprise-scale integrations reliably:
External requests enter through Azure API Management which handles authentication, rate limiting, and routing. Logic Apps orchestrate the business workflow using built-in connectors. Azure Service Bus provides reliable messaging between components with dead letter queues for failures. Function Apps handle complex C# transformation logic that Logic Apps cannot express. Azure SQL Database provides persistent storage. Application Insights monitors every step of the entire stack automatically.
Each layer has one responsibility. No layer does what another layer is designed for. This separation is what makes the architecture maintainable and debuggable at scale.
Summary
Azure Function Apps are the C# powerhouse of the Azure integration stack. Serverless execution means zero infrastructure management. Six trigger types connect to every Azure service. Bindings eliminate boilerplate connection code. Durable Functions handle complex long-running workflows.
Combined with Logic Apps for orchestration, Service Bus for messaging, and APIM for the front door — Function Apps complete the enterprise integration toolkit on Azure.
Originally published at TechStack Blog — https://calm-island-0a7b4b30f.7.azurestaticapps.net/
Follow for weekly posts on Azure integration, C#, and cloud engineering.
Top comments (0)