Preventing Serverless Vendor Lock-in with Design Patterns

Gregor Hohpe recently published an article proposing a paradigm shift to address vendor lock-in concerns on serverless cloud applications. Designing a solution using well-known patterns decouples its functional characteristics from the underlying cloud implementation, making it easier to avoid lock-in or to go multi-cloud.

Even though it is commonly said that cloud platform service offerings are fundamentally equivalent to one another, they have enough differences to make direct ports of non-trivial use cases impossible.

Portability is, thus, a valid concern to keep in mind when designing systems, especially if they are meant for multi-cloud deployments. Thinking in portable terms is, however, not always straightforward.

The author argues that a significant obstacle is “mental lock-in”. On the one hand, previous experiences may limit one’s thought pattern, making it challenging to adopt different architectures. On the other hand, modern cloud platforms make it tempting to describe one’s solutions in terms of service offerings. Doing so makes it difficult to translate the solutions onto a different platform.

Thinking only in platform services loses your application’s design intent and mentally locks you in.

Service mapping tables are too high-level to accurately describe portability because the specific service capabilities don’t correspond on a one-to-one basis. Further, the set of cloud services used doesn’t necessarily express the solution’s needs or the designer’s intent.

A typical route in the software engineering world is to build a portability layer on top of the specific service implementations. The author points out that such an approach can quickly lead to a lowest-common-denominator effect. This effect is a disadvantage because it prevents adopting innovations in the quickly-evolving area of cloud applications.

Instead of thinking in terms of implementation-level abstractions, Hohpe suggests it is better to think in terms of design-time abstractions. Being a “technology-neutral design-time vocabulary”, design patterns make useful abstractions to apply at design-time.

Expressing your solution as design patterns simplifies porting it to another platform.

By expressing a solution in terms of design patterns, both the architect’s intent and the solution’s needs become apparent.

Image source: “Concerned about Serverless Lock-in? Consider Patterns!”

Any design patterns used, e.g., aggregators, pub-sub channels, orchestrators, can be implemented using service offerings particular to each cloud vendor. Sometimes, these offerings may need to be combined to implement a specific design pattern, which is not a disadvantage.

Service combinations then become an implementation detail instead of a design choice.

The author adds that a system design needs to be expressed using a “cohesive language that forms a single vocabulary”. One can use multiple pattern languages to form this vocabulary, but it is necessary to have a clear view of the system aspect to which they are applied. For example, data flows can be designed using enterprise integration patterns, but components could be best built using object-oriented patterns.

A pattern language expresses the developer’s intent in a service-neutral language.

Platform advances also mean that the trade-offs required by patterns change. This evolution means that, for example, serverless cloud platforms may favour using patterns different from the ones preferred on older platforms. New patterns may also appear, emerging from widespread use.

Leave a Comment