Azure Functions: Small Pieces of Code That Wake Up When Something Happens

Azure Functions: Small Pieces of Code That Wake Up When Something Happens

A beginner-friendly guide to Azure Functions, the serverless service that runs your code in response to events, scales automatically and charges only for what you use, explained step by step with everyday analogies.

Imagine a helpful neighbour who sleeps in the next room. You do not pay the neighbour a monthly salary. Instead, you ring a bell whenever you need something done: water the plants, sign for a parcel, switch on the generator. The neighbour wakes up, does that one job, and goes back to sleep. If ten parcels arrive at once, ten neighbours show up. If nothing happens all night, nobody is paid. Azure Functions works like this bell and these neighbours, except that the neighbours are small pieces of your code.

In this guide we begin with the simple question “what is serverless?”, and slowly build up to triggers, bindings, hosting plans, scaling, Durable Functions, security, monitoring and cost. No earlier knowledge is assumed. Every new word is explained when it first appears, usually with a comparison from daily life. Features, limits and prices evolve, so treat this guide as a map of ideas and confirm specifics in the current Azure documentation.

1What Is Azure Functions?

It is a service for running small units of code in the cloud, triggered by events, without managing servers.

Normally, to run a program in the cloud, you create a server, install software, keep the server running day and night and look after its updates. The program waits for work, and you pay for the server whether work arrives or not. This is wasteful when the work comes only now and then.

Azure Functions offers a different way. You write a small function, which is a piece of code that does one job, such as resizing a picture, processing an order or sending a message. You tell Azure what should start it: a web request, a timer, a new file, a message in a queue or many other events. When the event happens, Azure runs your function. When the work is done, the resources are released. You do not manage servers, and you pay only for the time and resources that your code uses.

This style is called serverless computing. The word does not mean that there are no servers. It means that you do not see or manage them. Azure decides where and how to run your code, and adds or removes capacity automatically as the number of events changes.

Simple Analogy

Think of the difference between owning a car and using a ride-hailing app. With a car, you pay for parking, servicing and insurance even when it is parked. With the app, you pay only when you travel. Azure Functions is the ride-hailing app for running code.

Words you will meet again and again

Term 1

Function

A single piece of code that does one job and runs when its trigger fires.

Term 2

Function App

A container for one or more functions that are deployed, scaled and configured together.

Term 3

Trigger

The event that makes a function run, such as a web request, a timer or a new message. Every function has exactly one.

Term 4

Binding

A declared connection to data, such as a queue or a database, so that your code reads or writes it with little plumbing.

Term 5

Hosting Plan

The choice that decides how your function app scales, how it is billed and which features it has.

Term 6

Cold Start

The short delay when a function runs after a quiet period and a fresh instance must start first.

Event-driven
code runs when something happens
Auto-scale
from zero to many instances as events arrive
Pay per use
billed by executions and resources used

2Why Does Azure Functions Exist?

Because a lot of useful work is small, occasional and driven by events.

Think about the tasks that make up a typical business system. When a customer uploads a photo, a thumbnail must be made. When an order is placed, a confirmation email must be sent. Every night, old records must be cleaned up. When a sensor reports a high temperature, an alert must be raised. None of these tasks needs a whole server running all day. Each needs a small piece of code at the right moment.

Building these tasks on traditional servers means paying for idle time, planning capacity for the busiest moment and handling updates and failures yourself. Azure Functions removes this burden so that developers can focus on the logic, and the platform handles the scaling and infrastructure.

Focus on code, not servers

You write the logic, and Azure takes care of provisioning, patching and scaling the machines that run it.

Pay for what you use

With consumption-style plans, there is no charge while nothing is running, which suits spiky and occasional workloads.

Scale automatically

Ten events or ten million, the platform adds instances as needed without manual intervention.

Connect to many services easily

Triggers and bindings link functions to queues, storage, databases and event streams with very little code.

Move fast

A small function can go from idea to running in the cloud within hours, which helps with prototypes and glue code between systems.

i
Good to Know

Functions are not the best fit for everything. Long-running processes, very chatty applications with heavy shared state, and software that needs full control of the operating system may be better served by other services. We compare the options later in this guide.

3Core Concepts: Functions, Function Apps, Triggers and Bindings

Four simple ideas explain almost everything about how Azure Functions is organised.

1

Function

The smallest unit. It has a name, some code, one trigger and optionally several bindings. It should do one job well.

2

Function app

The unit of deployment and scaling. All functions inside one app share the same hosting plan, settings, runtime version and scale instances.

3

Trigger

The event that starts the function. A function has exactly one trigger. The trigger also passes data into the function, such as the content of a message.

4

Bindings

Optional, declarative connections. Input bindings bring data in, such as reading a record. Output bindings send data out, such as writing a message to a queue.

flowchart LR
  T["Trigger: new message in queue"] --> F["Function: process order"]
  IB["Input binding: read customer record"] --> F
  F --> OB1["Output binding: write to database"]
  F --> OB2["Output binding: send email message"]
        
FIG 1 — A function with one trigger, one input binding and two output bindings
Simple Analogy

A function is like a clerk at a counter. The trigger is the bell on the counter that wakes the clerk. Input bindings are the files placed on the desk for the clerk. Output bindings are the outgoing trays where the clerk puts the results. The function app is the whole office where several clerks work under the same management.

Why bindings matter

Without bindings, your code would need to open connections, handle authentication and manage details for every service it touches. With bindings, you declare what you need, and the runtime does the plumbing. This keeps functions short and focused. Bindings are optional, and you can always use the standard software libraries of a service directly when you need more control.

!
Common Mistake

Putting many unrelated functions into one function app because it is convenient. They then share scaling, settings and failures, and a noisy function can starve the others. Group functions that belong together and have similar scaling needs, and separate the rest.

4Inside the Machine: How Functions Actually Run

A look behind the curtain explains scaling, cold starts and many surprises.

Each function app runs on one or more instances. An instance is a virtual machine or container that hosts the Functions runtime, which is called the host, together with your code. The host listens for trigger events, calls your function with the event data, handles bindings and reports results and logs.

A separate component, the scale controller, watches the event sources of your function app. For example, it looks at the length of a queue or the lag of an event stream. When it sees more work than the current instances can handle, it adds instances. When work decreases, it removes them. On plans that scale to zero, it can stop all instances when there is nothing to do and start one when an event appears.

Part 1

Functions Host

The runtime that listens for triggers, invokes your code, manages bindings and sends telemetry.

Part 2

Language Worker

The process that runs your code in its own language, communicating with the host. In the recommended .NET model, it runs separately from the host.

Part 3

Scale Controller

The platform component that watches event sources and decides how many instances should run.

Part 4

Storage Account

Used by the host for internal bookkeeping such as keys, leases, timer state and checkpoints. A function app needs one.

1

An event occurs

A message arrives in a queue, a file is uploaded, a timer fires or a web request comes in.

2

The scale controller notices

If no instance is running, or if existing ones are busy, it arranges for instances to start.

3

The host starts and loads your code

A new instance starts the host and the language worker and loads your function app. This is the cold start.

4

The trigger delivers the event

The host reads the event, prepares input bindings and invokes your function with the data.

5

Your code runs

The function does its work, using output bindings or libraries to write results.

6

Completion is recorded

The host marks the event as processed, for example by deleting the queue message, and reports telemetry.

sequenceDiagram
  participant S as Event Source
  participant C as Scale Controller
  participant H as Functions Host Instance
  participant F as Your Function Code
  participant O as Output Service
  S->>C: New events waiting
  C->>H: Start or add instance
  H->>S: Read event
  H->>F: Invoke with event data
  F->>O: Write result
  F-->>H: Finished
  H->>S: Mark event as processed
        
FIG 2 — The journey of an event through the Functions runtime
Simple Analogy

A taxi dispatcher watches the number of waiting passengers and sends more cars when the queue grows. Each car has a driver, which is the host, who reads the destination and drives the route, which is your code. When passengers stop coming, cars are sent home.

i
Why the Storage Account Matters

Because the host stores keys, timer schedules, leases and checkpoints in the storage account, problems with that account can break your function app. Use a dedicated, healthy storage account in the same region, and prefer identity-based access instead of shared keys where supported.

5Triggers and Bindings in Practice

The list of triggers is the best way to see what Functions can do for you.

TriggerFires whenTypical use
HTTPA web request arrivesAPIs, webhooks and small web back ends
TimerA schedule is reachedNightly clean-up, reports, periodic checks
Queue storageA message appears in a storage queueSimple background work
Service BusA message arrives in a queue or topicReliable business messaging with ordering and dead-letter support
Event HubsEvents arrive in a streamTelemetry and high-volume event processing
Event GridAn Azure or custom event is publishedReacting to changes such as a resource being created
Blob storageA file is created or updatedImage processing, file imports
Cosmos DB and SQLData changes in a databaseReacting to updates and keeping systems in sync
Other connectorsMessages arrive from other brokers and systemsIntegration with systems such as Kafka or RabbitMQ

Examples of triggers with bindings

Photo thumbnail maker

The trigger is a new file in a storage container. An input binding provides the file content. An output binding writes the smaller image to another container.

Order confirmation

The trigger is a message in a service bus queue. The function reads the order, writes a record to a database through an output binding and sends a message to an email service.

Nightly report

A timer trigger fires at midnight. The function queries data, builds a summary and stores it for the morning.

Webhook receiver

An HTTP trigger receives a notification from an external service, validates it and places a message on a queue for further processing.

Choice

Queue Storage vs Service Bus

Queue storage is simple and cheap. Service Bus adds features such as topics, sessions, duplicate detection and dead-letter queues for enterprise messaging.

Choice

Event Grid vs Event Hubs

Event Grid delivers discrete notifications about things that happened. Event Hubs ingests large continuous streams of events for analysis.

Simple Analogy

A home has several kinds of bell: the doorbell, the alarm clock, the phone ringtone and the smoke alarm. Each tells you something different has happened and needs a different response. Triggers are the different bells for your code.

!
Common Mistake

Using an HTTP trigger and a long synchronous chain of calls for work that should be asynchronous. Instead, accept the request quickly, place the work on a queue and let another function process it, so that the caller does not wait or time out.

6Hosting Plans and Cold Starts

The hosting plan is the most important choice you make for a function app.

PlanScalingCold startNetworkingBest for
Flex ConsumptionEvent-driven, fast, scales to zero, with optional always-ready instancesReduced, and can be avoided with always-ready instancesSupports virtual network integrationMost new serverless workloads, including those needing private networking
ConsumptionEvent-driven, scales to zeroPossible after idle periodsLimited networking featuresSimple, spiky workloads. An older plan, so check the current recommendation and retirement notices
PremiumEvent-driven with pre-warmed instances, always at least one runningAvoided through pre-warmed instancesFull virtual network featuresSteady or latency-sensitive workloads with longer runs
Dedicated (App Service plan)Manual or rule-based scaling on reserved machinesNone when always onFull featuresTeams that already pay for spare App Service capacity
Container Apps hostingEvent-driven scaling on a container platformDepends on minimum replicasContainer Apps networkingTeams that run containers and want Functions programming on the same platform
flowchart TD
  Q["Choose a hosting plan"] --> A{"Need private networking or fast scale with no idle cost?"}
  A -->|"Yes"| FX["Flex Consumption"]
  A -->|"Need constant warm instances and long runs"| PR["Premium"]
  A -->|"Already have spare App Service capacity"| DD["Dedicated"]
  A -->|"Standardised on containers"| CA["Container Apps hosting"]
        
FIG 3 — A simple way to think about choosing a hosting plan

Understanding cold starts

When no instance is running and an event arrives, a new instance must start, load the runtime and your code, and then process the event. This extra delay is the cold start. It may be a fraction of a second or several seconds depending on the language, the size of your code and its dependencies, and the plan.

Keep packages small

Large dependency sets and heavy start-up work lengthen cold starts. Remove unused libraries and do expensive set-up lazily.

Use always-ready or pre-warmed instances

Plans that offer them keep some instances ready, which removes cold starts for the first requests, at a cost.

Accept it where it does not matter

Background processing rarely cares about a one-second delay. Reserve warm instances for user-facing calls that need a quick response.

Simple Analogy

A tea stall that opens only when a customer walks up must light the stove first, so the first cup takes longer. A stall that keeps the stove warm serves immediately but burns fuel all day. Plans trade cold-start delay against idle cost in the same way.

!
Check Plan Status

Hosting plans evolve. Microsoft has announced changes to older plans, including retirement dates for some configurations, and recommends newer options for new work. Always read the current documentation before choosing a plan for a long-lived system.

7Scaling and Concurrency

Scaling happens at two levels: more instances, and more work at once on each instance.

Scaling out means adding instances. Concurrency means how many executions run at the same time on one instance. Both matter. If each function call is quick and light, one instance can run many in parallel. If each call is heavy, more instances are needed sooner.

Level 1

Instance Scale-Out

The platform adds or removes instances based on the trigger source, with different rules for queues, streams and web requests, and within the limits of your plan.

Level 2

Per-Instance Concurrency

Settings control how many messages or requests one instance processes at once. Too high can overload memory or downstream systems, and too low wastes capacity.

Level 3

Maximum Instance Limits

You can cap the number of instances, to protect databases and external services from being overwhelmed.

Level 4

Partition-Based Scale for Streams

For stream sources, scale is related to the number of partitions, since each partition is read by one instance at a time.

1

Know your downstream limits

Find out how many connections and requests your database, external APIs and other services can take.

2

Set maximum scale accordingly

Cap instances and concurrency so that a burst of events cannot flatten your dependencies.

3

Test with realistic bursts

Send many events at once and watch latency, errors and throttling in the downstream systems.

4

Tune and monitor

Adjust concurrency and limits, and set alerts on queue backlog and processing delay.

Simple Analogy

A bank can serve more customers by opening more counters, which is scaling out, or by training each clerk to handle two customers at once, which is concurrency. But if the vault has only one door, adding counters will not help, because the vault is the bottleneck.

!
Common Mistake

Letting functions scale freely against a database that supports only a limited number of connections. The functions are happy, the database falls over, and the retries make things worse. Always set limits that respect the weakest link.

8Durable Functions: Workflows That Remember

Ordinary functions are short and stateless. Durable Functions add long-running, stateful workflows.

Some jobs take many steps over minutes, hours or days. An order might need payment, then stock reservation, then shipping, with waiting between steps and the possibility of failure at any point. Writing this with plain functions means building your own state tracking, retry logic and timers. Durable Functions is an extension that does this for you.

In Durable Functions, you write an orchestrator function that describes the workflow as ordinary code: do this, then wait for that, then do these three in parallel. The orchestrator calls activity functions, which perform the real work. The framework saves progress to storage after each step. If the instance stops, the workflow resumes from where it left off, by replaying the orchestrator’s history.

Type 1

Orchestrator Function

Describes the workflow. Must be deterministic, which means it must make the same decisions when replayed.

Type 2

Activity Function

Does one unit of real work, such as calling an API or writing to a database. May do anything.

Type 3

Entity Function

Holds small pieces of state with operations, such as a counter or a shopping cart, accessed safely one operation at a time.

Type 4

Client Function

Starts, queries and manages orchestrations, usually from an HTTP or queue trigger.

PatternIdeaExample
Function chainingRun steps in order, passing results alongValidate order, charge payment, create shipment
Fan-out and fan-inRun many tasks in parallel, then combine resultsProcess thousands of files, then build one summary
Async HTTP APIStart a long job, return a status address, let clients check progressReport generation that takes minutes
MonitorPoll until a condition is met, with timers between checksWait until a remote job finishes
Human interactionWait for an approval, with a timeoutManager approves an expense within three days
flowchart TD
  S["Start orchestration"] --> A1["Activity: validate order"]
  A1 --> A2["Activity: charge payment"]
  A2 --> P["Fan out"]
  P --> B1["Activity: reserve item 1"]
  P --> B2["Activity: reserve item 2"]
  P --> B3["Activity: reserve item 3"]
  B1 --> J["Fan in: combine results"]
  B2 --> J
  B3 --> J
  J --> A3["Activity: create shipment"]
        
FIG 4 — A durable orchestration using chaining and fan-out and fan-in
Simple Analogy

A project manager keeps a notebook of every step done and every step waiting. If the manager falls ill, a replacement reads the notebook and continues exactly where things stopped. The orchestrator is the manager, the activities are the workers and the saved history is the notebook.

i
The Determinism Rule

Because the orchestrator is replayed, it must not use random numbers, current time, direct network calls or other non-repeatable behaviour inside its own code. Put such things in activities or use the framework’s special features, which are safe for replay.

!
Common Mistake

Putting heavy work or network calls directly in the orchestrator. It breaks replay and makes results unpredictable. Keep orchestrators small and logical, and let activities do the actual work. Also keep the data passed between steps small.

9Reliability: Retries, Poison Messages and Idempotency

In a world of failures, good functions assume that things will be tried more than once.

Most event sources in Azure Functions deliver messages at least once. This means that a message is never lost, but it can occasionally be delivered more than once, for example after a crash or a timeout. If your function is not prepared for repeats, you may charge a customer twice or send duplicate emails.

Concept 1

At-Least-Once Delivery

Every message is delivered at least once. Duplicates are possible, so design for them.

Concept 2

Idempotency

An operation is idempotent if doing it twice has the same effect as doing it once. This is the key defence against duplicates.

Concept 3

Retries

When a function fails, many triggers retry automatically. You can also configure retry policies with delays that grow over time.

Concept 4

Poison Messages

A message that fails again and again is set aside, in a poison queue or dead-letter queue, so that it does not block the rest.

1

Make operations idempotent

Use unique identifiers for each message, check whether work was already done and use safe update patterns such as upserts.

2

Fail loudly for real errors

Let exceptions propagate so that the trigger can retry, instead of silently swallowing errors.

3

Configure retries sensibly

Use a limited number of retries with growing delays, so that temporary problems heal but permanent ones do not retry forever.

4

Handle poison messages

Monitor the poison or dead-letter queue, alert on new items and have a process to inspect, fix and replay them.

Simple Analogy

If a courier delivers a parcel twice by mistake, it is harmless when you simply sign for the same order number once and refuse the duplicate. Signing for every delivery without checking the order number leaves you with two parcels and a double bill.

!
Common Mistake

Catching every exception and logging it without rethrowing. The trigger believes the work succeeded, the message is removed and the data is lost. Handle only errors you can truly fix, and let others fail so that they can be retried or sent to a poison queue.

10Configuration: Settings, Host Files and Secrets

Where you put settings decides how safe and flexible your function app is.

Place 1

Application Settings

Named values stored with the function app in Azure and passed to your code as environment variables. They are different for each environment.

Place 2

Host Configuration File

A file that sets behaviour of the runtime for all functions in the app, such as logging levels, retry defaults and concurrency settings.

Place 3

Local Settings File

Used only on a developer’s computer, to hold settings and test connection strings. It must never be committed to source control.

Place 4

Key Vault References

Application settings that point to secrets in Azure Key Vault. The platform fetches the secret using the app’s managed identity.

Identity-based connections

Many triggers and bindings can connect to Azure services using the function app’s managed identity instead of connection strings with keys. This removes secrets from configuration entirely.

Separate settings per environment

Keep development, test and production values separate, and build the code once so the same package runs everywhere.

Feature flags and central configuration

For many apps, a central configuration service lets you change behaviour without redeploying code.

Simple Analogy

A restaurant keeps the recipe the same in every branch, but the local manager changes the quantities, suppliers and opening hours for each city. The code is the recipe, and the settings are the local adjustments.

!
Common Mistake

Committing the local settings file with real connection strings to a repository. Anyone with repository access can then reach your cloud resources. Exclude the file from source control and use Key Vault and managed identities in the cloud.

11Developing, Testing and Deploying

A good workflow lets you build on your own machine and release safely to the cloud.

1

Develop locally

Use Azure Functions Core Tools or an editor extension to run the Functions host on your computer, with local emulators for storage and queues, and debug with breakpoints.

2

Write tests

Keep business logic in ordinary classes or modules that can be tested without the runtime, and keep the function method thin.

3

Build a package in a pipeline

A pipeline compiles the code, runs tests and creates a deployment package.

4

Deploy using a package

Deploy the zipped package so that the app runs directly from it, which gives consistent, quick and repeatable releases.

5

Use slots or staged rollout where available

On plans that support deployment slots, release to a staging slot, test and swap into production with little downtime. Check which plans support slots today.

6

Verify and monitor

Check health, logs and key metrics after release, and roll back if needed.

Language

Many Languages

Functions supports several languages, including C#, JavaScript and TypeScript, Python, Java and PowerShell, plus custom handlers for others. Check the current supported versions.

Model

Isolated Worker Model for .NET

The recommended way to run .NET functions is in a separate worker process. The older in-process model has announced end of support, so use the isolated model for new work and plan migration for old apps.

Runtime

Runtime Versions

Function apps run on a version of the Functions runtime. Keep apps on supported versions and upgrade before older ones are retired.

Automation

Infrastructure as Code

Define the function app, storage, identity and settings in templates, so that environments are repeatable.

Simple Analogy

A bakery tests a new recipe in a small trial batch in the back kitchen, then packs it in standard boxes and ships it to all shops on the same day. Local development, packaging and pipeline-based deployment give your code the same repeatable path to production.

!
Common Mistake

Editing code directly in the portal for production functions. There is no review, no tests and no history, and the next deployment may overwrite the change. Treat production as read-only, and release only through pipelines.

12Security for Functions

Functions are small, but they are often public entry points to your systems, so protect them well.

1

Control who can call HTTP functions

HTTP functions can be anonymous, require a function key, or require an admin key. Keys are simple shared secrets and are not strong identity. For real user or application security, use platform authentication with an identity provider.

2

Use built-in authentication

The platform can require sign-in with Microsoft Entra ID or other providers before requests reach your code.

3

Use managed identities

Let the function app authenticate to other Azure services without secrets, and give it only the permissions it needs.

4

Protect secrets

Use Key Vault references, keep secrets out of code and settings files, and rotate any keys you must use.

5

Restrict the network

Use access restrictions, private endpoints and virtual network integration on plans that support them, so that only intended callers and services can connect.

6

Validate input and keep code safe

Treat all input as untrusted, validate it, keep dependencies up to date and follow safe coding practices.

7

Log and monitor

Record who called what, watch for unusual patterns and alert on failures and abuse.

Level

Anonymous

No key is needed. Appropriate only when the function is protected in other ways, such as an authentication layer in front.

Level

Function Key

Callers must send a key specific to the function or app. Simple protection for service-to-service calls and webhooks.

Level

Admin Key

A powerful key that opens all functions and management endpoints. Guard it carefully.

Simple Analogy

A shop can leave its front door open, give regular customers a shared door code, or check each visitor’s identity card at the entrance. Keys are like the shared code: easy, but anyone who learns it can enter. Identity checks are much stronger for sensitive services.

!
Common Mistake

Leaving an HTTP function anonymous because “it is just a small helper”. Public functions are found and abused quickly, and may reach databases and other resources through their identity. Authenticate every function that is exposed to the internet.

13Networking and Connectivity

Functions often need to reach private systems, and sometimes they must be reachable only privately.

Direction

Outbound: Virtual Network Integration

Lets the function app call resources inside your virtual network, such as private databases, and send outbound traffic through a firewall or NAT gateway.

Direction

Inbound: Private Endpoints and Restrictions

Lets only callers inside your network, or from approved addresses, reach the function app, removing its public exposure.

Direction

Hybrid Connections

A way to reach specific on-premises resources without opening a full network connection, on plans that support it.

Direction

Triggers from Private Sources

On plans with network support, triggers can read from queues and streams that are locked inside a virtual network.

Plan features matter

Not all plans offer all networking features. Flex Consumption, Premium and Dedicated plans provide the broadest options, while older consumption configurations are more limited. Check the plan’s current abilities before designing.

Fixed outbound addresses

If a partner must allow your function’s address, route outbound traffic through a NAT gateway or firewall so that a stable address is used.

Storage account networking

If you lock down the function app’s own storage account, make sure the app can still reach it through its network setup, or it will fail to start.

Simple Analogy

A courier company can have a door open to the public street, a pass that lets its riders enter a gated campus, and a private entrance only for staff. Outbound integration, inbound restriction and private endpoints are those passes and doors for your function.

!
Common Mistake

Locking down the storage account, the queue and the database one by one and then wondering why the function stops working. Each step of the path needs both permission and a network route. Test connectivity after every network change.

14Monitoring and Troubleshooting

Because functions run unattended and in parallel, good telemetry is essential.

Azure Functions integrates with Application Insights, a monitoring service that collects information about every invocation, including duration, success or failure, dependency calls and exceptions. It also draws maps of how your functions and the services they use are connected, and traces a request across several functions.

Signal 1

Invocation Counts and Failures

How many times functions ran and how many failed. A sudden change often signals a problem.

Signal 2

Duration

How long executions take, including high percentiles. Rising duration may point to slow dependencies or cold starts.

Signal 3

Queue and Stream Backlog

The amount of waiting work. A growing backlog means functions cannot keep up.

Signal 4

Instance Count and Throttling

How many instances run and whether dependencies are rejecting calls.

Signal 5

Live Metrics

A near real-time view of requests, failures and servers, useful during releases and incidents.

Signal 6

Poison and Dead-Letter Queues

Counts of messages that could not be processed, which need human attention.

SymptomLikely causeFirst check
Function never firesWrong trigger settings, disabled function, storage or connection problemHost start-up logs, app settings, storage account access
Slow first request after quiet timeCold startPlan type, package size, always-ready or pre-warmed settings
Messages processed more than onceAt-least-once delivery, timeouts, retriesIdempotency of the code, execution time against visibility timeout
Messages end up in poison queueRepeated failures from bad data or bugsException details in logs, message content
Backlog keeps growingNot enough scale, slow dependencies or low concurrencyInstance count, maximum limits, downstream latency
Executions time outWork exceeds the plan’s time limitPlan timeout, split work or use Durable Functions
Simple Analogy

A manager of many small delivery riders needs a map showing where each rider is, how long each delivery took and which parcels came back undelivered. Application Insights is that map and logbook for your functions.

i
Use Structured Logs and Sampling

Log meaningful, structured messages with identifiers that let you follow one order through several functions. For very busy apps, use sampling to control telemetry volume and cost, while keeping errors visible.

15Understanding and Controlling Cost

Functions can be extremely cheap, but a few details can surprise you.

PlanWhat you pay forCost character
ConsumptionNumber of executions and resource use measured in gigabyte-seconds, with a free monthly grantZero when idle, grows with use
Flex ConsumptionExecution time and memory of running instances, plus optional charges for always-ready instancesPay per use with a choice to pay for warm capacity
PremiumProcessor and memory time of instances, including the minimum warm onesHigher base cost, predictable performance
DedicatedThe App Service plan machines, whether busy or notFixed monthly cost
Extra Cost

Storage Account

The host’s own storage account has small charges for operations and capacity, which can grow with many functions or heavy trigger polling.

Extra Cost

Application Insights

Telemetry is billed by volume. High-traffic functions with verbose logging can make this the biggest item.

Extra Cost

Triggers and Bindings Services

Queues, event hubs, databases and networking have their own charges, which usually exceed the cost of the functions.

Extra Cost

Data Transfer

Data leaving Azure or moving between regions is charged.

1

Right-size memory and duration

Make functions efficient. Faster code and smaller memory settings reduce the cost of each execution.

2

Batch where possible

Process messages in batches when the trigger supports it, which reduces the number of executions and overhead.

3

Avoid unnecessary polling and chatter

Do not call functions in tight loops or create infinite trigger cycles, such as a function writing to the same container that triggers it.

4

Control telemetry volume

Use sampling and sensible log levels, and avoid logging large payloads.

5

Pick the plan that matches the pattern

Consumption-style plans suit spiky traffic. For steady heavy traffic, a Premium or dedicated plan may be cheaper per execution. Compare using real numbers.

6

Set budgets and alerts

Watch spending, and alert on sudden jumps in executions that could mean a loop or an attack.

Simple Analogy

Paying a courier per parcel is cheap when parcels are few, but if a bug makes the shop send a million parcels to itself, the bill will be huge. Per-use pricing rewards efficiency and punishes loops, so watch the counters.

!
Common Mistake

Creating a function that writes to the same storage container that triggers it. Each write triggers another run, creating an endless loop and a surprising bill. Use separate containers for input and output, and test with small data first.

16Azure Functions Compared with Other Options

Several Azure services run your logic, and each fits a different style of work.

ServiceStyleBest forLess suited for
Azure FunctionsCode-first, event-driven, small unitsGlue code, event processing, APIs, scheduled tasks and workflows with Durable FunctionsVery long uninterrupted processes, or software that needs full machine control
Logic AppsLow-code visual workflows with many connectorsIntegrating business systems with little code, approvals and enterprise connectorsHeavy custom computation
Azure Container AppsContainers with autoscaling and jobsMicroservices, long-running workers, custom runtimesTiny pieces of code where containers are overkill
App ServiceAlways-on web app hostingFull web applications with steady trafficEvent-driven scale to zero
Azure Kubernetes ServiceFull container orchestrationComplex platforms and custom controlSimple tasks, since operations effort is high
Virtual MachinesFull control of the operating systemLegacy and special softwareShort, event-driven snippets
Event Grid and Event HubsEvent routing and ingestion, not computeDelivering events to functions and other handlersRunning your code themselves
flowchart TD
  Q1{"Is the work event-driven and small?"} -->|"Yes"| Q2{"Prefer code or visual designer?"}
  Q2 -->|"Code"| FN["Azure Functions"]
  Q2 -->|"Visual and connectors"| LA["Logic Apps"]
  Q1 -->|"No, long-running or containerised services"| Q3{"Need Kubernetes API?"}
  Q3 -->|"No"| CA["Container Apps"]
  Q3 -->|"Yes"| AKS["Kubernetes Service"]
        
FIG 5 — A simple way to choose among Azure compute options for logic
Simple Analogy

Functions are like a helper you call for a specific errand. Logic Apps is a flowchart assistant who connects office systems by following a diagram. Container Apps is a small crew running a stall. App Service is a shop that is open all day. Pick the helper that fits the task.

Functions and Logic Apps together

Many solutions use Logic Apps for the workflow and connectors, and call Functions for pieces that need custom code.

Functions and Container Apps together

Functions can be hosted on Container Apps, letting teams use the Functions programming model with container tooling and networking.

i
Start Simple

If the job is small and driven by events, start with Functions. Move to a heavier service only when you hit a real limit, such as run time, custom runtime needs or complex multi-service orchestration.

17Design Patterns That Work Well

These approaches appear again and again in successful serverless systems.

Pattern: Queue-Based Load Leveling

A front function accepts work quickly and puts it on a queue. Worker functions process the queue at a steady, controlled pace, protecting back-end systems from sudden bursts.

Pattern: Event-Driven File Processing

A new file in storage triggers a function that validates, transforms and stores the result, with failures sent to a poison queue for review.

Pattern: Claim Check

Large payloads are stored in blob storage, and only a small reference is sent through queues and events. Functions fetch the payload when they need it.

Pattern: Fan-Out and Fan-In with Durable Functions

A large job is split into many small tasks processed in parallel, and their results are combined at the end.

Pattern: Saga for Long Business Processes

A durable orchestration coordinates steps across services and runs compensating actions, such as refunds, if a later step fails.

Pattern: Serverless API Back End

HTTP functions behind an API gateway handle requests, using managed identities to read and write data, with authentication at the gateway.

Pattern: Scheduled Housekeeping

Timer functions run clean-up, reports and synchronisation at fixed times, costing little because they run briefly.

flowchart LR
  U["Client"] --> API["HTTP Function: accept request"]
  API --> Q["Queue"]
  Q --> W["Worker Function: process with limits"]
  W --> DB["Database"]
  W --> PQ["Poison Queue for failures"]
  W --> N["Notification Function"]
        
FIG 6 — Queue-based load leveling with a poison queue for failures
“Do one small thing, do it safely twice, and let the platform do the scaling.”

18Real-World Examples

Azure Functions quietly powers a wide range of everyday systems.

An e-commerce order flow

When an order is placed, a message triggers functions that validate it, reserve stock, call the payment service, email the customer and update analytics. During sales, the number of instances grows automatically and then shrinks again.

A media company processing uploads

Uploaded videos and images trigger functions that create thumbnails, check content and extract metadata. A durable orchestration handles larger, multi-step encoding jobs and waits for completion.

Internet of Things data handling

Devices send readings to an event stream. Functions read the stream, filter and enrich readings, store them and raise alerts when thresholds are crossed.

A bank’s scheduled reports

Timer functions assemble daily statements and compliance reports, write them to secure storage and notify teams. Retry policies and alerts handle failures.

Integrating software-as-a-service tools

Webhook functions receive notifications from external services, check signatures and place events on queues, connecting separate systems without a permanent server.

AI document pipelines

New documents trigger functions that extract text, call AI services, store results and update a search index, scaling with the volume of uploads.

Advantages

  • No servers to manage, with automatic scaling
  • Pay-per-use pricing and a free monthly grant on consumption-style plans
  • Rich triggers and bindings for many services
  • Durable Functions for reliable long workflows
  • Quick development and many supported languages

Disadvantages / Trade-offs

  • Cold starts on plans that scale to zero
  • Execution time limits on some plans
  • At-least-once delivery requires idempotent design
  • Many small functions can be harder to understand and debug as a whole system
  • Plans and runtime versions change, so documentation needs regular rechecking

19Anti-Patterns to Avoid

These habits regularly cause duplicate work, outages and surprise bills.

ANTI-PATTERN-01 Avoid
Problem

Functions assume that each message arrives exactly once, and perform non-repeatable actions such as charging cards or sending emails without checks.

Why It’s Harmful

Duplicates occur after retries and timeouts. Customers are charged twice, receive repeated messages and data becomes inconsistent.

Correct Approach

Design for at-least-once delivery. Use unique identifiers, check before acting, use upserts and make every operation safe to repeat.

ANTI-PATTERN-02 Avoid
Problem

A single function tries to run a long, multi-step process, or functions call each other in long synchronous chains over HTTP.

Why It’s Harmful

Time limits are reached, failures in the middle leave work half done, and a slow step blocks the whole chain and its callers.

Correct Approach

Use queues between steps, or Durable Functions for workflows, so that each step is small, retryable and its state is saved.

ANTI-PATTERN-03 Avoid
Problem

Functions scale without limits against databases and external services, and keep important state in memory or on local disk.

Why It’s Harmful

Bursts overwhelm dependencies, and instances disappear at any time taking their in-memory state with them.

Correct Approach

Cap instances and concurrency to match dependency limits, and keep all state in managed stores such as databases, caches and storage.

ANTI-PATTERN-04 Avoid
Problem

HTTP functions are left anonymous, secrets sit in settings or source control, and production code is edited in the portal.

Why It’s Harmful

Public endpoints are abused, secrets leak, and untracked changes make the system unpredictable and hard to restore.

Correct Approach

Authenticate every exposed function, use managed identities and Key Vault, and deploy only through reviewed pipelines.

ANTI-PATTERN-05 Avoid
Problem

A function writes its output to the same place that triggers it, or errors are caught and ignored so that failures disappear silently.

Why It’s Harmful

Endless trigger loops create huge bills, and swallowed errors cause lost data with no alert.

Correct Approach

Use separate input and output locations, let genuine failures propagate for retry and poison handling, and alert on failures and unusual execution counts.

20Best Practices and a Starter Checklist

Walk through these steps whenever you plan a new function app.

1

Confirm that Functions fits the job

Check that the work is event-driven and short enough, or can be split with queues or Durable Functions.

2

Choose the hosting plan on purpose

Match scaling, networking, cold start and cost needs to a plan, and check the current plan status and retirement notices.

3

Keep functions small and focused

Do one job per function, keep business logic in testable code and group functions by shared scaling needs.

4

Design for retries and duplicates

Make operations idempotent, configure retries, handle poison messages and avoid swallowing exceptions.

5

Respect downstream limits

Set maximum instances and concurrency, use queues to level load, and test with bursts.

6

Secure everything exposed

Authenticate HTTP functions, use managed identities and Key Vault, restrict the network and keep dependencies updated.

7

Deploy through pipelines

Use packages, infrastructure as code, staged releases and rollbacks, and keep environments consistent.

8

Monitor and control cost

Use Application Insights with sampling, alert on failures, backlog and unusual execution counts, set budgets and review the plan against real usage.

!
Frequent Beginner Mistakes

Assuming exactly-once delivery, building long chains of synchronous calls, scaling without limits, keeping state in memory, leaving HTTP functions anonymous, editing production in the portal, creating trigger loops, ignoring poison queues and not checking plan and runtime retirement notices.

21Frequently Asked Questions

Q1What does serverless mean in Azure Functions?

It means that you do not manage the servers. You provide code, and Azure provisions, scales and maintains the machines that run it. There are still servers underneath, but you do not see or operate them.

Q2What is the difference between a trigger and a binding?

A trigger is the event that starts a function, and every function has exactly one. A binding is an optional, declared connection to data, such as reading a record or writing a message, either as input or output.

Q3What is a cold start and how can I reduce it?

A cold start is the extra delay when a new instance must start before running your function, usually after a quiet period. You can reduce it by keeping packages small, avoiding heavy start-up work and using plans or settings that keep instances warm, such as always-ready or pre-warmed instances.

Q4Which hosting plan should I choose?

For most new serverless workloads, Flex Consumption is a strong default because it scales quickly and supports private networking. Choose Premium for steady, latency-sensitive or long-running work, Dedicated if you already have spare App Service capacity, and check the current documentation for plan status and limits.

Q5What are Durable Functions used for?

They are used for reliable, long-running workflows with many steps, waiting, parallel work and human approvals. The framework saves progress, so that a workflow can continue after failures or restarts.

Q6Why did my function run twice for one message?

Most triggers use at-least-once delivery, so duplicates can happen after retries, timeouts or crashes. Make your function idempotent, so that repeating the same message does no harm.

Q7How do I protect an HTTP function?

Do not leave it anonymous if it is exposed to the internet. Use platform authentication with an identity provider where possible, use function keys only for simple service-to-service cases, and restrict the network, use managed identities and keep secrets in Key Vault.

Q8How do I stop my functions from overwhelming a database?

Cap the maximum number of instances, limit concurrency per instance and put a queue between the caller and the worker functions, so that work is processed at a controlled pace. Add retries with delays in your code.

Q9How can I keep costs low?

Make functions efficient, batch work, avoid loops and unnecessary polling, control telemetry volume with sampling, choose the plan that matches your traffic pattern and set budgets and alerts for unexpected spikes.

Q10Should I use Functions, Logic Apps or Container Apps?

Use Functions for code-first, event-driven tasks. Use Logic Apps when a visual workflow with many connectors fits better. Use Container Apps for containerised services, long-running workers or custom runtimes. Many solutions combine them.

22Summary and Key Takeaways

Azure Functions runs small pieces of code in response to events, without any servers for you to manage. A function has one trigger and optional bindings, and functions are grouped in function apps that scale together according to a hosting plan. The scale controller adds and removes instances as events arrive, so you pay for use rather than idle time. Durable Functions add reliable long-running workflows, while good design for retries, idempotency, poison messages and downstream limits keeps systems safe. With managed identities, Key Vault, careful networking, pipeline-based deployment, strong monitoring and attention to cost, Azure Functions lets small teams build responsive, scalable systems quickly.

Key Takeaways

  • Event-driven and serverless — code runs only when a trigger fires, scaling automatically and billing by use, with no servers for you to manage.
  • Triggers, bindings and apps — each function has one trigger and optional bindings, and functions in a function app share scaling, settings and plan.
  • The plan shapes everything — choose among Flex Consumption, Consumption, Premium, Dedicated and Container Apps hosting for scaling, networking, cold start and cost, and check retirement notices.
  • Design for failure — expect at-least-once delivery, make operations idempotent, configure retries, handle poison messages and let real errors fail.
  • Protect your dependencies — cap instances and concurrency, level load with queues and test with realistic bursts.
  • Use Durable Functions for workflows — orchestrators, activities and entities give reliable, stateful, long-running processes, as long as orchestrators stay deterministic.
  • Secure, observe and control cost — authenticate exposed functions, use managed identities and Key Vault, monitor with Application Insights, deploy through pipelines and watch for loops and telemetry growth.