Choosing Between App Service, Functions, AKS, and VMs
Choosing Azure compute is not a contest to find the most modern service. App Service, Azure Functions, Azure Kubernetes Service, and Virtual Machines can all run production workloads, but they transfer different responsibilities to the platform and leave different responsibilities with the workload team. The architectural question is therefore not “which service is best?” It is “which hosting model gives this application the control it needs without forcing the team to operate complexity that does not create value?”
This decision belongs directly in the current AZ-305 exam, where infrastructure design includes recommending compute solutions based on workload requirements. For the Azure Solutions Architect Expert certification, candidates should be able to reason across hosting model, networking, scaling, availability, deployment, security, portability, team skills, and cost. Product features matter, but the operating model usually reveals the real tradeoff.
Start with the responsibility boundary before comparing features
Every compute choice defines a boundary between what Microsoft operates and what the customer operates. With a managed web platform, the team can focus heavily on application code and configuration. With Kubernetes, Microsoft manages the AKS control plane but the customer still owns significant cluster, workload, policy, networking, upgrade, and observability decisions. With virtual machines, the customer owns the guest operating system and much more of the runtime lifecycle. Functions can abstract even more infrastructure for suitable event-driven code.
That responsibility boundary should match the problem. If the application needs ordinary web hosting, choosing a platform that requires cluster administration can add risk without adding useful capability. If the workload needs privileged agents, unusual network behavior, custom operating-system configuration, or software that cannot fit a managed runtime, a more abstract service may be too restrictive. Architecture improves when teams deliberately buy or retain operational responsibility instead of inheriting it accidentally.
App Service fits web applications and APIs that benefit from a managed application platform
Azure App Service is designed for web applications, REST APIs, mobile back ends, and related application workloads without requiring the team to manage the underlying servers. It supports common language stacks and custom containers, and the platform provides integrated capabilities for deployment, scaling, certificates, authentication options, diagnostics, and network integration. For many conventional web systems, that removes infrastructure work while preserving enough application-level control.
The important test is whether the application can live comfortably within the platform boundaries. If the team needs a supported runtime, standard HTTP application behavior, predictable deployment, and managed scaling, App Service can keep the architecture straightforward. If the application depends on deep operating-system changes, unusual background processing, specialized network appliances, or a cluster-level scheduling model, forcing it into App Service may create workarounds that erase the benefits of the managed service.
Azure Functions is strongest when work is naturally event-driven and independently executable
Functions works well when code can be triggered by events such as messages, timers, HTTP calls, storage changes, or other signals, and when individual units of work can scale independently. Serverless hosting can reduce capacity management and align cost more closely with execution for suitable workloads. The model is especially useful for integration tasks, asynchronous processing, lightweight APIs, automation, and background logic that does not require an always-on server identity.
“Serverless” does not mean architecture-free. Teams still need to think about execution duration, concurrency, cold-start sensitivity, state management, idempotency, retry behavior, poison messages, networking, observability, and downstream service limits. A function that triggers thousands of parallel calls into a database can simply move the bottleneck. The correct design treats Functions as an event-driven compute model and designs the surrounding system for that behavior instead of assuming automatic scaling solves every dependency.
AKS makes sense when Kubernetes capabilities are requirements rather than aspirations
Azure Kubernetes Service is appropriate when the workload genuinely benefits from Kubernetes orchestration: multiple containerized services, explicit scheduling and resource policies, custom controllers, advanced deployment patterns, service meshes or platform extensions, portable Kubernetes APIs, and a team prepared to operate the cluster ecosystem. AKS removes the burden of running the Kubernetes control plane directly, but it does not remove the need to manage node pools, upgrades, workload security, ingress, storage, networking, policy, and day-two operations.
That is why Kubernetes administration and orchestration knowledge becomes relevant once AKS is chosen. An application does not become more reliable merely because it is placed in Kubernetes. The team must design readiness, disruption behavior, scaling, resource limits, secrets, network policy, observability, and upgrade processes. AKS is powerful when those controls are valuable; it is expensive complexity when the workload only needed a place to run a web process.
Virtual Machines remain the right answer when the operating system is part of the requirement
Virtual Machines provide the broadest compatibility and control among these options. They are often appropriate for lift-and-shift migrations, commercial software with specific operating-system assumptions, legacy applications that cannot be refactored quickly, specialized drivers or agents, and workloads whose installation or network behavior falls outside managed platform constraints. A VM can be the shortest path to Azure when changing the application would create unacceptable delivery risk.
The tradeoff is operational ownership. Guest patching, image management, endpoint protection, configuration drift, backup, scaling strategy, high availability, and software lifecycle remain significant responsibilities. Virtual machine scale sets and automation can reduce manual work, but the architecture should acknowledge that the team is operating an infrastructure platform. Choosing VMs because they are familiar can postpone modernization indefinitely; choosing them because the workload truly needs OS-level control can be completely rational.
Networking and security requirements can change which compute model is practical
Compute cannot be selected independently from network architecture. Workloads may require private inbound access, controlled outbound traffic, private endpoints to dependencies, hybrid connectivity, fixed egress, service-to-service identity, ingress inspection, or isolation between tiers. Each compute service supports these needs differently and with different configuration constraints. A service that looks simplest from a coding perspective may become awkward if the required network path does not fit its hosting model.
Security responsibilities also shift with abstraction. Managed platforms reduce the amount of operating-system hardening a team performs, but application identity, secrets, authorization, network exposure, dependency security, and software supply-chain controls still matter. AKS adds container and cluster policy concerns. VMs expose the widest host-management surface. The right choice minimizes unnecessary attack surface while retaining the controls the workload actually requires.
Scaling behavior and cost should be evaluated together under realistic demand
The services scale in different ways. App Service scales application instances within a plan. Functions can scale event-driven execution according to its hosting model. AKS can scale pods and node pools, with cluster capacity and scheduling behavior to manage. Virtual machines can scale through scale sets or other automation but retain infrastructure-level provisioning characteristics. Those mechanisms react differently to burst traffic, long-running work, stateful components, and dependencies with their own limits.
Cost comparisons must therefore include workload shape and operational labor, not just hourly resource prices. A VM may appear inexpensive but require ongoing administration. A Kubernetes platform can consolidate workloads but needs specialized operations. A serverless design can be efficient for intermittent execution but less attractive for constantly busy or resource-intensive processing depending on the hosting plan. Measure the expected demand profile and include the cost of operating the chosen abstraction.
Migration constraints and team skills are legitimate architecture requirements
A greenfield application can be shaped around the strengths of a managed platform. A migration may have to preserve frameworks, deployment packaging, state, network assumptions, or vendor support. The architect should distinguish between temporary constraints and permanent ones. Rehosting to VMs can be a deliberate first step if it reduces migration risk, provided the organization records whether and when further modernization is expected.
Team capability matters just as much. A service that is theoretically elegant but unfamiliar to the team can create slower incident response, poor security configuration, or fragile deployments. This does not mean architecture should never stretch skills; it means the learning and operating cost should be part of the decision. If Kubernetes is selected, invest in Kubernetes operations. If Functions becomes central, build strong event-driven design and observability practices. Architecture includes the humans who must run it.
A useful comparison matrix includes more than runtime support. Capture deployment model, network requirements, state, scaling behavior, startup sensitivity, operating-system control, portability needs, patching responsibility, upgrade responsibility, observability, security boundaries, recovery approach, and team ownership. Scoring the services is less important than exposing where a candidate violates a hard requirement. A single non-negotiable constraint can outweigh a long list of convenient features.
Proof-of-concept work should target the uncertain parts of that matrix. If private connectivity is the concern, test the real network path. If burst scaling is decisive, simulate the burst and the downstream dependency. If AKS is attractive for deployment flexibility, exercise upgrade and recovery rather than only demonstrating that a container starts. Architecture experiments are most valuable when they attack assumptions that could invalidate the decision.
Real solutions often use more than one compute model
The four services are not mutually exclusive at the solution level. A customer-facing web front end might run on App Service, event handlers in Functions, a specialized container platform in AKS, and a legacy dependency on VMs during a migration period. The architecture should choose the simplest appropriate model for each component while avoiding unnecessary fragmentation. Too many compute platforms can multiply deployment pipelines, monitoring patterns, security controls, and support skills.
The best decision is the one that can explain why each component needs its hosting model. Use App Service when managed web hosting fits. Use Functions when event-driven execution is the natural unit. Use AKS when Kubernetes control and orchestration capabilities are requirements the team is prepared to operate. Use VMs when operating-system control or compatibility is essential. AZ-305 architecture is about making those responsibility and tradeoff boundaries explicit, not declaring one Azure compute service the universal winner.