Building Portable Cloud Functions with Spring Cloud Function and Hexagonal Architecture - Part 3 (Azure)

Building Portable Cloud Functions with Spring Cloud Function and Hexagonal Architecture - Part 3 (Azure)

In Part 1, we built a Task Management System using Spring Cloud Function and Hexagonal Architecture, deploying it to Google Cloud Functions with Firestore. In Part 2, we proved the architecture by deploying the exact same domain code to AWS Lambda with DynamoDB. Now, we complete the trifecta: the same business logic running on Azure Functions with Cosmos DB.

No domain logic modifications. No business rule changes. Just infrastructure swapping.

This is the power of true cloud portability.


Recap: What We Built

Our Task Management System implements comprehensive business rules:

Create Operations:

  • Users cannot create more than 5 high-priority tasks per day
  • Task descriptions must be unique per user per day
  • Users cannot have more than 50 open tasks
  • Tasks must have valid priorities (LOW, MEDIUM, HIGH)

Read/Update/Delete Operations:

  • Users can only access their own tasks
  • Completed tasks cannot be modified

These rules live in our domain layer, completely cloud-agnostic.


The Azure Implementation Strategy

What Stays the Same (Zero Changes)

  • Domain entities - Task, TaskId, UserId, Priority, Status
  • Business rules - All validation logic remains identical
  • Application services - TaskService orchestration unchanged
  • Use case interfaces - Same inbound ports
  • Function definitions - Same Spring Cloud Function beans

What Changes (Infrastructure Only)

  • 🔄 Inbound adapter - Azure Functions HTTP Trigger handler
  • 🔄 Outbound adapter - Cosmos DB replaces DynamoDB/Firestore
  • 🔄 Maven configuration - Azure dependencies and plugins
  • 🔄 Infrastructure as Code - Terraform for Azure resources
  • 🔄 Configuration - Azure-specific application properties


Azure-Specific Implementation

1. Maven Dependencies

The project uses Spring Cloud Azure with a profile-based approach:

Article content

2. Cosmos DB Document Mapping

Azure Cosmos DB uses a document-based model with partition keys for scalability:

Article content

Key differences from other cloud providers:

  • @Container annotation maps to Cosmos DB container
  • @PartitionKey defines the partition strategy (userId for data locality)
  • Spring Data Cosmos handles the low-level API interactions

3. Cosmos DB Repository Implementation

Article content

Key points:

  • @Profile("azure") ensures this adapter is only active on Azure
  • PartitionKey is required for delete operations in Cosmos DB
  • Queries leverage Cosmos DB's efficient indexing with composite indexes

4. Spring Data Cosmos Repository Interface

Unlike AWS Lambda and GCP Cloud Functions that work seamlessly with Spring Cloud Function's FunctionInvoker, Azure Functions requires a custom handler that bridges HTTP triggers to Spring Cloud Function beans:

Article content

Key implementation details:

  • Constructor injection of function beans from TaskFunctions.java
  • Manual JSON serialization using ObjectMapper for proper response formatting
  • Function routing via function.name header (same pattern as AWS/GCP)
  • Type-safe request handling with explicit type mapping
  • Fallback to defaultFunction for unknown function names

6. Application Configuration

Article content

Infrastructure as Code: Terraform for Azure

Main Resources

Article content

Deployment Process

Build and Deploy

Article content

Testing in Action

Function Routing

Spring Cloud Function uses a routing mechanism to direct requests:

Article content

Business Rules Validation

Article content

Key Benefits Demonstrated

1. Pure Business Logic

The domain layer contains no Azure-specific code. Rules like "max 5 high-priority tasks per day" are expressed in pure Java.

2. Testable Architecture

Article content

3. Infrastructure Flexibility

Swapping between GCP Firestore, AWS DynamoDB, and Azure Cosmos DB requires only:

  • New outbound adapter implementation
  • Configuration change
  • Zero domain logic changes


The Power of True Portability

Our Azure implementation completes the trilogy and proves that Hexagonal Architecture + Spring Cloud Function delivers on its promise:

  • Zero business logic changes - Rules work identically across all three clouds
  • Minimal infrastructure code - Only repository adapter needed per cloud
  • Same development experience - Testing and debugging remain consistent
  • Risk mitigation - True cloud portability reduces vendor lock-in
  • Cost optimization - Freedom to choose the most cost-effective provider


Get Started

Ready to deploy the same Task Management System to Azure Functions?

🔗 Complete source code: GitHub Repository

Repository Structure - Complete Multi-Cloud

Article content

Quick Commands Reference

Article content

Three clouds, one codebase, infinite possibilities.

Follow me to get notified about future articles! Have questions about the Azure implementation? Drop them in the comments below.

⭐ Star the GitHub repo if you found this series valuable!


This is such a clean example of why hexagonal architecture pays off in the real world. “One codebase, three clouds, zero business logic changes” is the kind of portability claim most teams don’t actually achieve. What was the trickiest part of the Azure Functions + Cosmos DB adapter compared to AWS/GCP?

Like
Reply

To view or add a comment, sign in

More articles by Erick Beloti

Others also viewed

Explore content categories