× Install ThecoreGrid App
Tap below and select "Add to Home Screen" for full-screen experience.
B2B Engineering Insights & Architectural Teardowns

Serverless clean architecture without vendor lock-in

Serverless clean architecture helps isolate business logic and reduce cloud dependency. Let’s explore how this works in practice and where compromises arise.

The main issue with the serverless approach manifests not at the start, but during the scaling of the architecture. Functions as a Service simplifies operations: there is no need to manage infrastructure, patches, and scaling. However, this introduces hidden coupling with a specific provider. Entry points, triggers, SDKs, and even the deployment model differ between AWS and Azure. As a result, business logic begins to “leak” into the infrastructure layer. This is particularly noticeable when attempting migration: code that was considered portable requires modifications. Degradation begins when the same function is implemented differently due to variations in triggers and adapters.

The solution is built around serverless clean architecture and the idea of strict isolation of business logic. Spring Cloud Function is used as an abstraction over FaaS. It allows functions to be described as pure input-output, while adaptation to the cloud is moved to a separate layer. In combination with Gradle modules, this provides separation: domain logic, cloud adapters, and infrastructure code (IaC). This is a compromise. We pay with additional complexity in the build and project structure, but gain in portability. It is important to note that Spring Cloud Function does not completely eliminate vendor lock-in. It reduces its impact, but cloud-specific code still remains in the adapters.

The implementation shows where the real boundaries of abstraction lie. For Azure, the function is declared with an HTTP trigger directly in the code, including basic security (API key). For AWS, the trigger is absent from the code and is defined through API Gateway in Infrastructure as Code. This is a fundamental difference. In AWS, it is also necessary to explicitly specify the handler and function name through environment variables. These details cannot be unified without losses. Therefore, the architecture separates:

  • business logic (pure functions)
  • cloud adapters (Spring Cloud Function for AWS and Azure)
  • infrastructure (Terraform CDK)

Terraform CDK is used as a single layer for managing infrastructure. It generates Terraform configurations through a programming language. This provides a unified way to describe resources across different clouds. However, even here there is no complete unification: function parameters, triggers, and configurations remain specific. The architecture does not hide differences but localizes them.

A separate engineering aspect is the scaling model. In serverless, not the entire service scales, but individual functions. This increases efficiency (throughput) and reduces resource overconsumption. However, it requires stricter separation of responsibilities. If a function does too much, the advantages are lost. This is directly related to clean architecture: the cleaner the boundaries, the more predictable the scaling.

The results of this approach are qualitative. The initial data does not contain specific metrics for latency or cost. However, there is a noticeable reduction in dependency on a single cloud and simplification of business logic reuse. The team can deploy the same logic in AWS and Azure with minimal changes. However, it is impossible to completely avoid differences in implementation. This is an expected limitation.

In the industry, such an approach is seen as pragmatic. A fully cloud-agnostic architecture is rarely achievable without sacrificing platform capabilities. Therefore, the focus shifts to controlling points of dependency. Serverless clean architecture does not eliminate lock-in but makes it manageable. This is especially important in conditions where requirements for deployment and cloud selection may change.

Reference source

×

🚀 Deploy the Blocks

Controls: ← → to move, ↑ to rotate, ↓ to drop.
Mobile: use buttons below.