CH11-03: Processing with Functions and Container Apps
Goal
The previous section explained how Event Grid routes notifications. Routing is only the beginning. Something still has to receive the event, validate it, decide what reaction is needed, call dependencies, record outcomes, and fail safely.
That work belongs to an event handler.
The durable idea is:
Event processing still needs a deliberate runtime, identity, state, retry, and observability design.
The Short Version
An event handler is code that reacts to an event.
The simple question is:
Should this handler run as an Azure Function or a container?
The better architecture question is:
What kind of processing is this, and what operating responsibility does it create?
Functions and Container Apps can both be good choices. The runtime should fit the workload shape, dependency needs, processing duration, deployment model, scaling behavior, and team operations.
Event Grid
|-- Function handler for a small event task
|-- Container App worker for containerized or heavier processing
What an Event Handler Owns
A handler does more than receive an event.
It usually owns several responsibilities:
| Responsibility | Why It Matters |
|---|---|
| Validation | The handler should reject or isolate malformed, unexpected, or unauthorized events. |
| Identity | The handler needs secure access to storage, databases, queues, APIs, and secrets. |
| Idempotency | The same event may arrive or be processed more than once. Repeating work should not corrupt state. |
| Dependency calls | Downstream APIs and data stores can fail, throttle, or return partial results. |
| State | The handler may need to record progress, outcomes, or deduplication markers. |
| Retry behavior | Temporary failures should be retried carefully; permanent failures should become visible. |
| Observability | Logs, metrics, traces, and correlation IDs help teams understand asynchronous flow. |
Serverless or managed containers reduce infrastructure work. They do not remove these application responsibilities.
When Azure Functions Fit
Azure Functions is often a strong fit for small event-triggered units of work.
It works well when the handler:
Has a clear trigger and a focused job.
Can complete within a reasonable processing window.
Does not need a highly customized runtime environment.
Scales based on events or messages.
Benefits from trigger bindings and managed serverless operations.
Examples include extracting metadata after a file upload, validating an event payload, sending a notification, placing durable work onto a queue, or updating a small status record.
Functions are not automatically the right answer for every event-driven workflow. If a handler grows into many steps, holds complex state, calls several unreliable dependencies, or needs long-running processing, the design may need durable orchestration, Service Bus, Container Apps, or another workflow pattern.
When Container Apps Fit
Azure Container Apps is often useful when the team wants to run containerized event processors without operating a full Kubernetes platform.
It can fit when the handler:
Requires a custom runtime, library, or packaged worker image.
Performs heavier processing than a small function.
Runs as a background worker that consumes from a queue or event source.
Needs container-based deployment consistency with the rest of the platform.
Benefits from managed scaling and environment-level networking controls.
For example, a media team might use a Function to react quickly to an upload event and enqueue work, then use a containerized worker to generate thumbnails, transcode video, or run document analysis libraries.
Choosing the Runtime
Use the Chapter 4 compute idea: choose the operating boundary that fits the work.
| Question | Function Signal | Container Apps Signal |
|---|---|---|
| How focused is the task? | Small, event-triggered unit of work. | Worker or service with a broader processing responsibility. |
| How custom is the runtime? | Standard supported runtime is enough. | Custom container image or toolchain matters. |
| How long or heavy is processing? | Shorter and lightweight. | Heavier, longer, or dependency-rich processing. |
| How does the team deploy? | Function app deployment fits. | Container image deployment fits existing practices. |
| What operations are needed? | Trigger scale and function monitoring are enough. | Worker scaling, container logs, environment settings, and queue consumption patterns matter. |
This is not a ranking. A mature event-driven architecture may use both.
Example: Document Upload Processing
A document platform receives uploaded PDFs.
At first, the event flow is simple:
Blob uploaded
-> Event Grid
-> Function extracts file metadata
-> Metadata stored for search
Later, the team adds heavier processing. Documents need OCR, classification, virus scanning, and preview generation. The workflow now needs larger libraries, clearer worker ownership, and stronger failure handling.
The design can evolve:
Blob uploaded
-> Event Grid
-> Function validates event and creates work item
-> Service Bus queue
-> Container App worker processes document
The Function remains small and responsive. Service Bus protects the work. The container worker owns the heavier processing.
Common Mistakes
Assuming serverless removes state, retry, identity, or observability decisions.
Choosing Functions for long or complex workflows only because the work started with an event.
Ignoring duplicate delivery and failing to make handlers idempotent.
Calling downstream systems without timeout, retry, and failure classification rules.
Letting tiny handlers become a hidden workflow with no clear monitoring or owner.
If Someone Asks You
How do you choose an event-processing runtime in Azure?
A good answer is:
I choose the runtime based on the shape of the processing, not only the trigger. Azure Functions fit small event-driven units of work and simple trigger-based handlers. Azure Container Apps fit containerized workers, custom runtimes, or heavier processing. In both cases I still design identity, validation, idempotency, retries, logging, metrics, and failure handling.
What You Should Remember
Choose event processing by workload shape, runtime needs, failure behavior, and operations.
Questions to Check Your Understanding
Why might Functions fit a simple event handler?
Why might Container Apps fit a worker?
What does idempotency protect against?