Azure App Services and Serverless Computing

Nilay BarotNilay Barot
8 min read

Welcome back to our Azure Compute series! After exploring Virtual Machines and Scale Sets, let's dive into Azure's Platform-as-a-Service (PaaS) offerings: Azure App Services and Azure Functions. These services enable you to build and deploy applications without managing the underlying infrastructure.

Azure App Services: Web Apps Made Simple

What is Azure App Service?

Azure App Service is a fully managed platform for building, deploying, and scaling web apps. It supports multiple programming languages and frameworks, allowing developers to focus on writing code rather than managing servers.

Key Features

  • Multiple Language Support: ASP.NET, .NET Core, Java, Ruby, Node.js, PHP, Python
  • Built-in DevOps: Continuous integration and deployment from GitHub, Azure DevOps, and more
  • Auto-scaling: Automatically scale based on demand
  • Global Scale: Deploy to multiple regions worldwide
  • Security and Compliance: Built-in authentication, SSL certificates, and compliance certifications

Types of App Services

1. Web Apps

Host web applications and REST APIs:

# Create a web app
az webapp create \
  --resource-group myResourceGroup \
  --plan myAppServicePlan \
  --name myUniqueWebApp \
  --runtime "DOTNET|8.0"

2. API Apps

Build and host RESTful APIs:

# Deploy API app with continuous deployment
az webapp deployment source config \
  --name myApiApp \
  --resource-group myResourceGroup \
  --repo-url https://github.com/username/api-repo \
  --branch main \
  --manual-integration

3. Mobile Apps

Backend services for mobile applications:

# Create mobile app backend
az webapp create \
  --resource-group myResourceGroup \
  --plan myAppServicePlan \
  --name myMobileBackend \
  --runtime "DOTNETCORE|6.0"

App Service Plans

App Service Plans define the compute resources for your apps:

TierBest ForFeatures
Free/SharedDevelopment, testingLimited resources, no custom domains
BasicSmall production appsCustom domains, SSL, manual scale
StandardProduction workloadsAuto-scale, staging slots, daily backups
PremiumHigh-performance appsAdvanced auto-scale, VNet integration
IsolatedEnterprise appsDedicated environment, advanced security

Deployment Slots

Deployment slots enable zero-downtime deployments:

# Create a staging slot
az webapp deployment slot create \
  --name myWebApp \
  --resource-group myResourceGroup \
  --slot staging

# Deploy to staging
az webapp deployment source config \
  --name myWebApp \
  --resource-group myResourceGroup \
  --slot staging \
  --repo-url https://github.com/username/app-repo

# Swap staging to production
az webapp deployment slot swap \
  --name myWebApp \
  --resource-group myResourceGroup \
  --slot staging \
  --target-slot production

Azure Functions: Serverless Computing

What are Azure Functions?

Azure Functions is a serverless compute service that lets you run event-driven code without managing infrastructure. You pay only for the time your code runs, making it cost-effective for sporadic workloads.

Key Benefits

  • Event-Driven: Triggered by various events (HTTP requests, timers, storage changes)
  • Pay-per-Execution: Only pay when your function runs
  • Auto-Scaling: Automatically scales from zero to thousands of instances
  • Multiple Languages: C#, JavaScript, Python, Java, PowerShell, and more

Function Triggers

HTTP Trigger

[FunctionName("HttpTriggerCSharp")]
public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
    ILogger log)
{
    log.LogInformation("C# HTTP trigger function processed a request.");

    string name = req.Query["name"];

    string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
    dynamic data = JsonConvert.DeserializeObject(requestBody);
    name = name ?? data?.name;

    string responseMessage = string.IsNullOrEmpty(name)
        ? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
        : $"Hello, {name}. This HTTP triggered function executed successfully.";

    return new OkObjectResult(responseMessage);
}

Timer Trigger

[FunctionName("TimerTriggerCSharp")]
public static void Run([TimerTrigger("0 */5 * * * *")]TimerInfo myTimer, ILogger log)
{
    log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
}

Blob Storage Trigger

[FunctionName("BlobTriggerCSharp")]
public static void Run(
    [BlobTrigger("samples-workitems/{name}", Connection = "AzureWebJobsStorage")] Stream myBlob,
    string name,
    ILogger log)
{
    log.LogInformation($"C# Blob trigger function processed blob\n"
                      $"Name: {name}\n"
                      $"Blob Size: {myBlob.Length} bytes");

    // Process the blob content
    // Example: Read blob content
    using (var reader = new StreamReader(myBlob))
    {
        string content = reader.ReadToEnd();
        log.LogInformation($"Blob content: {content}");
    }
}

Service Bus Queue Trigger

[FunctionName("ServiceBusQueueTrigger")]
public static async Task Run(
    [ServiceBusTrigger("myqueue", Connection = "ServiceBusConnection")] string myQueueItem,
    ILogger log)
{
    log.LogInformation($"C# ServiceBus queue trigger function processed message: {myQueueItem}");

    try
    {
        // Process the queue message
        var order = JsonConvert.DeserializeObject<Order>(myQueueItem);

        // Business logic here
        await ProcessOrderAsync(order);

        log.LogInformation($"Successfully processed order {order.Id}");
    }
    catch (Exception ex)
    {
        log.LogError(ex, "Error processing queue message");
        throw; // Re-throw to handle poison messages
    }
}

private static async Task ProcessOrderAsync(Order order)
{
    // Implementation here
    await Task.CompletedTask;
}

public class Order
{
    public string Id { get; set; }
    public string CustomerId { get; set; }
    public decimal Amount { get; set; }
}

Dependency Injection Example

// Startup.cs
public class Startup : FunctionsStartup
{
    public override void Configure(IFunctionsHostBuilder builder)
    {
        builder.Services.AddHttpClient();
        builder.Services.AddScoped<IOrderService, OrderService>();
        builder.Services.AddSingleton<IConfiguration>(provider =>
        {
            var config = new ConfigurationBuilder()
                .AddEnvironmentVariables()
                .Build();
            return config;
        });
    }
}

// Function with Dependency Injection
public class OrderFunction
{
    private readonly IOrderService _orderService;
    private readonly ILogger<OrderFunction> _logger;

    public OrderFunction(IOrderService orderService, ILogger<OrderFunction> logger)
    {
        _orderService = orderService;
        _logger = logger;
    }

    [FunctionName("ProcessOrder")]
    public async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Function, "post", Route = "orders")] HttpRequest req)
    {
        try
        {
            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            var order = JsonConvert.DeserializeObject<Order>(requestBody);

            var result = await _orderService.ProcessOrderAsync(order);

            return new OkObjectResult(result);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error processing order");
            return new BadRequestObjectResult("Failed to process order");
        }
    }
}

public interface IOrderService
{
    Task<string> ProcessOrderAsync(Order order);
}

public class OrderService : IOrderService
{
    public async Task<string> ProcessOrderAsync(Order order)
    {
        // Business logic implementation
        await Task.Delay(100); // Simulate processing
        return $"Order {order.Id} processed successfully";
    }
}

Creating Azure Functions

# Create a function app
az functionapp create \
  --resource-group myResourceGroup \
  --consumption-plan-location eastus \
  --runtime dotnet \
  --runtime-version 8 \
  --functions-version 4 \
  --name myFunctionApp \
  --storage-account mystorageaccount

Hosting Plans

1. Consumption Plan

  • Pay-per-execution
  • Automatic scaling
  • 5-minute execution timeout (default)

2. Premium Plan

  • Pre-warmed instances
  • Unlimited execution duration
  • VNet connectivity

3. Dedicated Plan

  • Run on App Service Plan
  • Predictable pricing
  • Full control over scaling

Durable Functions

For complex, stateful functions in serverless environments:

[FunctionName("OrderProcessing")]
public static async Task<string> RunOrchestrator(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    var orderId = context.GetInput<string>();

    // Step 1: Validate order
    await context.CallActivityAsync("ValidateOrder", orderId);

    // Step 2: Process payment
    await context.CallActivityAsync("ProcessPayment", orderId);

    // Step 3: Ship order
    await context.CallActivityAsync("ShipOrder", orderId);

    return "Order processed successfully";
}

Best Practices

App Services

  1. Use Deployment Slots: Implement blue-green deployments
  2. Enable Application Insights: Monitor performance and errors
  3. Configure Auto-Scale: Handle traffic variations automatically
  4. Secure Your Apps: Use authentication providers and SSL certificates
  5. Optimize Performance: Use CDN for static content

Azure Functions (.NET Specific)

  1. Keep Functions Small: Single responsibility principle
  2. Handle Cold Starts: Use Premium plans for consistent performance
  3. Use Dependency Injection: Register services in Startup.cs for better testability
  4. Implement Proper Error Handling: Use try-catch and structured logging
  5. Async/Await Best Practices: Use ConfigureAwait(false) for better performance
  6. Secure Function Keys: Rotate keys regularly and use Azure Key Vault
  7. NuGet Package Management: Keep packages updated and minimize dependencies
  8. Monitor Costs: Watch execution counts and duration

Real-World Architecture Example

E-commerce Platform

Frontend (React) → App Service
     ↓
API Gateway → Azure Functions
     ↓
┌─────────────────────────┐
│ • User Authentication  │
│ • Order Processing     │
│ • Inventory Updates    │
│ • Email Notifications  │
└─────────────────────────┘
     ↓
Azure Storage + Cosmos DB

Implementation Steps

  1. Frontend: Deploy React app to App Service
  2. API Functions: Create HTTP-triggered functions for each API endpoint
  3. Background Processing: Use queue-triggered functions for async tasks
  4. Monitoring: Implement Application Insights across all services

Cost Optimization

App Services

  • Right-size your plan: Start small and scale up as needed
  • Use shared plans: For development and testing
  • Implement auto-shutdown: For non-production environments

Azure Functions

  • Optimize execution time: Reduce function duration
  • Use appropriate hosting plans: Consumption for sporadic loads
  • Implement efficient triggers: Avoid unnecessary executions

Monitoring and Debugging

Application Insights Integration

public static class Function1
{
    [FunctionName("Function1")]
    public static async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
        ILogger log)
    {
        log.LogInformation("C# HTTP trigger function processed a request.");

        // Your function logic here

        return new OkObjectResult("Function executed successfully");
    }
}

Log Analytics Queries

// Function execution times
requests
| where cloud_RoleName == "myFunctionApp"
| summarize avg(duration), count() by name
| order by avg_duration desc

Common Pitfalls to Avoid

  1. Over-provisioning App Service Plans: Choose the right tier for your needs
  2. Ignoring Cold Starts: Consider Premium functions for consistent performance
  3. Not implementing proper monitoring: Set up alerts and dashboards
  4. Security oversights: Always use HTTPS and implement authentication
  5. Lack of error handling: Implement comprehensive error handling and logging

What's Next?

In our next post, we'll explore Container Services in Azure, covering:

  • Azure Container Instances (ACI)
  • Azure Kubernetes Service (AKS)
  • Azure Container Registry
  • Container deployment strategies

Conclusion

Azure App Services and Functions provide powerful platforms for building modern, scalable applications. App Services offer a managed environment for web applications, while Functions enable serverless architectures that can significantly reduce costs and complexity.

By combining these services, you can build robust, scalable applications that automatically adapt to demand while minimizing operational overhead.

Key Takeaways:

  • App Services provide managed hosting for web applications and APIs
  • Azure Functions enable event-driven, serverless computing
  • Both services integrate seamlessly with other Azure services
  • Choose the right hosting plan based on your performance and cost requirements
  • Implement proper monitoring and security from the start

Tags: Azure, App Services, Azure Functions, Serverless, PaaS, Web Applications

Category: Azure Compute Series

Estimated Reading Time: 12 minutes

0
Subscribe to my newsletter

Read articles from Nilay Barot directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Nilay Barot
Nilay Barot

As an experienced software engineer with a demonstrated history of working in the computer software industry, I'm skilled in Win Forms, WPF, ASP.NET Web forms, C++, C#, JavaScript, React and Go. I'm a software engineering professional with a Bachelor of Engineering - BE focused in Computer Engineering from Mahatma Gandhi Institute of Technology. Throughout my career, I've been passionate about building high-quality software that meets the needs of users, and I'm always striving to learn and grow as a developer. With a keen eye for detail and a commitment to excellence, I'm dedicated to delivering results that exceed expectations. In my free time, I enjoy reading books on technology, playing video games, and exploring new software development trends. Let's connect on LinkedIn and share our experiences as technology enthusiasts.