Part 2: Building the Engine — Azure Compute Services
CloudVault needs to deploy its microservices. Marcus explores four compute options—Virtual Machines, App Service, Azure Functions, and Containers. We build a production-ready Java Spring Boot API and learn when to use each service for different workloads.
Part 2: Building the Engine — Azure Compute Services
Deploying CloudVault’s Microservices
The Deployment Challenge
Week two at CloudVault. Marcus has the API code ready, but now he faces a critical decision: how should he deploy it?
“We have options,” his architect explains. “Virtual Machines for full control, App Service for managed applications, Azure Functions for serverless, or Containers for flexibility.”
“Which one is right for us?” Marcus asks.
“That depends on your requirements,” she replies. “Let’s evaluate each option.”
The Compute Spectrum
Azure offers different compute services optimized for different patterns:
| Service | Best For | Scaling | Cost |
|---|---|---|---|
| Virtual Machines | Full control, custom OS | Manual | Higher |
| App Service | Web apps, APIs | Automatic | Medium |
| Azure Functions | Event-driven, short tasks | Automatic | Pay-per-execution |
| Containers (AKS) | Microservices, complex orchestration | Automatic | Medium-High |
Option 1: Azure App Service
Azure App Service is a managed platform for hosting web applications and APIs. You deploy your code; Azure handles infrastructure, scaling, and patching.
When to Use App Service
- You have a web application or REST API
- You want managed infrastructure (no VM management)
- You need automatic scaling based on demand
- You prefer simplicity over full control
Deploying a Spring Boot API
Create a Spring Boot application:
@SpringBootApplication@RestControllerpublic class AccountApiApplication {
@GetMapping("/api/accounts/{id}") public ResponseEntity<Account> getAccount(@PathVariable Long id) { Account account = accountService.getAccount(id); return ResponseEntity.ok(account); }
@PostMapping("/api/accounts") public ResponseEntity<Account> createAccount(@RequestBody CreateAccountRequest req) { Account account = accountService.createAccount(req); return ResponseEntity.status(HttpStatus.CREATED).body(account); }
public static void main(String[] args) { SpringApplication.run(AccountApiApplication.class, args); }}Deploy to App Service
# Create an App Service planaz appservice plan create \ --name plan-cloudvault-prod \ --resource-group rg-cloudvault-prod \ --sku B2 \ --is-linux
# Create a web appaz webapp create \ --resource-group rg-cloudvault-prod \ --plan plan-cloudvault-prod \ --name api-cloudvault-prod \ --runtime "JAVA|17-java17"
# Deploy your JAR fileaz webapp deployment source config-zip \ --resource-group rg-cloudvault-prod \ --name api-cloudvault-prod \ --src target/account-api.jarCost: ~$50-150/month depending on SKU
Option 2: Azure Functions
Azure Functions is serverless computing. You write functions that respond to events (HTTP requests, timers, messages). You pay only for execution time.
When to Use Functions
- You have event-driven workloads
- You need automatic scaling to zero
- You want pay-per-execution pricing
- Your functions are short-lived (< 10 minutes)
Building a Function
import com.microsoft.azure.functions.*;
public class AccountFunction {
@FunctionName("GetAccount") public HttpResponseMessage getAccount( @HttpTrigger( name = "req", methods = {HttpMethod.GET}, authLevel = AuthorizationLevel.ANONYMOUS, route = "accounts/{id}") HttpRequestMessage<Optional<String>> request, @BindingName("id") Long id, final ExecutionContext context) {
context.getLogger().info("Getting account: " + id);
Account account = accountService.getAccount(id);
return request.createResponseBuilder(HttpStatus.OK) .body(account) .build(); }}Deploy:
# Create a Function Appaz functionapp create \ --resource-group rg-cloudvault-prod \ --consumption-plan-location eastus \ --name func-cloudvault-prod \ --storage-account cvaultstorage \ --runtime java \ --runtime-version 17
# Deploy your codefunc azure functionapp publish func-cloudvault-prodCost: ~$0.20 per million executions + storage
Option 3: Containers (AKS)
Azure Kubernetes Service (AKS) orchestrates containerized applications. It’s powerful but complex.
When to Use AKS
- You have complex microservices
- You need sophisticated orchestration
- You’re already using Kubernetes
- You have DevOps expertise
Containerizing Your Application
Create a Dockerfile:
FROM openjdk:17-jdk-slimCOPY target/account-api.jar app.jarENTRYPOINT ["java", "-jar", "/app.jar"]Build and push:
# Build the imagedocker build -t account-api:latest .
# Push to Azure Container Registryaz acr build \ --registry cloudvaultacr \ --image account-api:latest .
# Deploy to AKSkubectl apply -f deployment.yamlCost: ~$100-300/month for a basic cluster
Marcus’s Decision
After evaluating the options, Marcus chooses App Service for CloudVault:
- It’s managed — no VM management
- It scales automatically — handles traffic spikes
- It’s cost-effective — reasonable pricing
- It’s simple — focus on code, not infrastructure
- It integrates well with other Azure services
“We can always migrate to AKS later if we need more complexity,” Marcus explains. “For now, App Service gives us what we need.”
Comparison: AWS Equivalents
| Azure | AWS |
|---|---|
| App Service | Elastic Beanstalk |
| Azure Functions | AWS Lambda |
| AKS | EKS |
| Virtual Machines | EC2 |
Key Takeaways
- App Service is best for web apps and APIs
- Azure Functions is best for event-driven, short-lived workloads
- AKS is best for complex microservices
- Virtual Machines give full control but require management
- Choose based on your requirements, not just the latest technology
What’s Next?
Marcus has deployed CloudVault’s API. Now he needs to design the data architecture. In the next chapter, we’ll explore Azure’s data services and build a scalable, multi-tier data architecture.
The engine is running. Now let’s store the treasures.
This is Part 2 of a 6-part series: “The Azure Ascent: A Backend Engineer’s Journey to Cloud Mastery.”