Azure Functions — Interview Prep Notes (ImageProcessor project)¶
Code-grounded notes on the actual ImageProcessor function you built, for quick recall at Siemens L2. Full theory reference: Study Notes/Azure/04. Azure Functions — Complete Reference.md.
What the function does¶
ProcessImage — BlobTrigger, fires on upload to originals/{name}. Reads the stream twice, produces two derivatives:
- 150x150 crop →
thumbnailscontainer - 800x800 max-fit →
webcontainer
Uses SixLabors.ImageSharp for resize, uploads via a fresh BlobServiceClient with DefaultAzureCredential (Managed Identity / Azure AD, not connection string) pointed at averblobstore.
Terminology to have cold¶
- Isolated worker model: your code runs in its own process, not inside the Functions host.
FUNCTIONS_WORKER_RUNTIME: dotnet-isolatedinlocal.settings.jsonconfirms this project uses it. Full control over .NET version (net8.0 here), required for .NET 8+. In-process is the deprecated alternative that shares the host process. - BlobTrigger binding expression:
"originals/{name}"— Azure extracts the blob's filename from the path and injects it as thestring nameparameter automatically. No manual parsing. - Consumption plan (implied by this being a simple learning demo): pay-per-execution, scales to zero, cold starts of 2-5s acceptable here since image processing is async and nobody's waiting on a response.
- Two storage accounts, two jobs — this project's
local.settings.jsonshows both: AzureWebJobsStorage(accountaverimagestore) — Functions runtime's own bookkeeping: blob trigger checkpointing, distributed locks so the same blob isn't processed twice, function state.BlobStorageConnection(accountaverblobstore) — your application data, where originals/thumbnails/web actually live. These are correctly separated in this project — good talking point on why (avoids conflating runtime noise with app data, cleaner access control).
Gap between the code and best practice — be ready to discuss this honestly¶
This is the most interesting part to walk through in an interview: you can show you know the "right" pattern even though the demo code takes shortcuts.
-
No three-line-function rule applied. The reference doc's own principle: a Function should be a thin adapter delegating to a portable interface (
IImageProcessor), with zero Azure-specific logic inside. ThisProcessImage.Runmethod has all the resize/upload logic inline — not extracted to a service. If asked "would you ship this as-is," the honest answer is no — you'd extract anIImageProcessor.ProcessAsync(stream, name)so the Function itself is 1-2 lines, matching the pattern you already use withIDocumentStorein AverAzure. -
Mixed credential strategy.
local.settings.jsonuses connection strings (AccountKey=...) for bothAzureWebJobsStorageandBlobStorageConnection, but the code itself constructsBlobServiceClientwithDefaultAzureCredential()(Managed Identity) rather than reading the connection string. This is a local-dev-only inconsistency — locally it likely falls back to Azure CLI/VS credential viaDefaultAzureCredential's credential chain rather than actually using theBlobStorageConnectionvalue. In deployed Azure, this would needStorage Blob Data Contributorrole granted to the Function App's identity onaverblobstore. Good to explain: "locally I authenticate via my own Azure CLI login through the default credential chain; in Azure this becomes the Function App's managed identity." -
New
BlobServiceClientper invocation. Every trigger fire constructs a brand newBlobServiceClient. Fine at low volume, but the reference pattern is to inject it once via DI (builder.Services.AddSingleton<BlobServiceClient>(...)inProgram.cs) so connections/credential tokens are reused.Program.cshere only wires up Application Insights — no custom DI registrations at all. Worth mentioning as the obvious next iteration. -
Double stream read via
stream.Position = 0. Works here because BlobTrigger gives you a seekableStream, but worth knowing this only works because Consumption plan's blob trigger buffers the blob into a seekable stream — not guaranteed for all trigger/stream types (e.g. HTTP request streams are often forward-only).
Likely interview questions and how to answer from this code¶
"Walk me through what happens when an image lands in Blob Storage."
Blob uploaded to originals/ → Consumption plan's blob trigger (backed by Azure Queue Storage polling under AzureWebJobsStorage) picks up the event, may take up to ~10 min in low-traffic scenarios due to polling → Function host spins up (or reuses a warm instance) → ProcessImage.Run invoked with the blob stream and extracted filename → resize twice → upload to two other containers.
"Why Functions here and not your Worker Service / RabbitMQ pattern from PEPPOL?" Straight from the reference doc's framing — image processing is sporadic, stateless, no strict latency requirement, no complex delivery guarantees. PEPPOL is steady throughput, stateful (correlation IDs, retries, reconciliation), latency-sensitive compliance webhooks. That contrast is the intended interview answer.
"What would break this in production?"
- Blob trigger polling delay (up to 10 min on Consumption) — unacceptable if near-real-time processing were required; would need Event Grid–based trigger instead.
- No error handling / retry visible in ProcessImage.Run — a failure mid-way (e.g. after thumbnail upload, before web upload) leaves inconsistent state with no compensation.
- No idempotency check — if the trigger fires twice for the same blob (queue-based triggers are at-least-once), both derivatives get regenerated and overwritten (harmless here since overwrite: true, but worth naming the guarantee explicitly: idempotent by virtue of deterministic output + overwrite, not by dedup logic).
"How is logging wired up and would you see everything in App Insights?"
host.json explicitly sets Function.ProcessImage.User: Information — necessary because isolated worker filters out Information by default; without that line your _logger.LogInformation calls in ProcessImage would silently never appear.
Quick facts to have ready¶
- Target framework: net8.0, isolated worker, Functions v4
- Packages:
Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs,SixLabors.ImageSharpfor resizing - Storage accounts:
averimagestore(runtime),averblobstore(app data) - Containers:
originals(trigger source),thumbnails(150x150 crop),web(800x800 max)