Services, Microservices and Stacks
For folks new to building serverless applications or to distributed systems in general, a lot of the jargon you encounter can be confusing. Ambiguous terms with several meanings along the abstract–concrete spectrum can make it difficult to explain concepts or suggest solutions.
Today I’m going to cover three such terms that are often (incorrectly) used interchangeably: services, microservices and stacks.
Before I address each term, I want to first show you a list of questions I’ve asked myself or been asked by others when deciding how to structure a serverless architecture for a new application:
- Do all serverless applications, by definition, imply the following of a service-oriented or microservices-based architecture?
- Do I need to split my application up into multiple logical microservices? What benefits will it give me?
- If yes, what microservices do I need and how will they communicate in a loosely coupled way?
- Should I create a Serverless Framework service for each microservice I’ve identified in my architecture design?
- I don’t care for or need discrete microservices and just want to group all my Lambda functions and other resources together in a monolithic deployment. Is this ok and if so, what do I need to be aware of?
- How should I name and structure my folders, files and modules within my code repo?
Answering these questions requires a strong understanding of each of the 3 terms and how they inter-relate. Let’s dig into each term…
Service
Service is the worst offender regarding ambiguity. Just within the context of cloud software engineering, I can think of 4 distinct uses:
- A hosted product supplied “as a service” by a cloud provider, e.g. S3, Lambda, DynamoDB
- A discrete component of a distributed system (e.g. within a Service-Oriented Architecture), e.g. an Orders Service
- A code module that acts as a layer over your business domain model and data access, but independent of the entrypoint interface such as the Lambda handler function
- A unit of organisation within the Serverless Framework
“I recommend splitting your application up into services” — not helpful!
Microservice
Microservice is a constriction of item 2 on the above list. Its defining attributes are being fine-grained and loosely coupled. Although it’s less ambiguous than service, many folks cannot agree on what exactly constitutes a microservices architecture. The “micro” prefix is unfortunate also — how small is micro (it sounds tiny!)? If my microservice is pretty big (30–40 Lambda functions), is it then just a service (definition 2)?
I’m less bullish on microservices than most serverless advocates — while they can be very powerful for large apps, in my experience certain attributes of them (e.g. having to deploy each one independently) can be an unnecessary overhead for many single-team projects building small- to medium-sized workloads.
Stack
A stack is a more concrete term and is generally understood to mean a collection of resources that are deployed together. It doesn’t make any implications around size or coupling like microservice does.
In AWS, a CloudFormation Stack allows you to deploy a logical group of cloud resources (Lambda functions, API Gateways, S3 buckets, etc) as a single unit using a transactional operation. Higher-level deployment frameworks such as the Serverless Framework and SAM make use of CloudFormation stacks under-the-hood. A single Serverless Framework service maps directly to a single CloudFormation stack. To my great disdain, CloudFormation still imposes a 200 resource limit on stack sizes which makes monolithic deployments more complicated.
A key point to understand about stacks — and one which took me quite a while to realise myself — is that a single logical (micro)service can potentially be composed of multiple stacks. An example of this is a microservice that includes resources that are a mix of those which are one of stateful/slow to change/slow to deploy (e.g. a Cognito User Pool, S3 bucket or a CloudFront distribution) and those which are stateless and change frequently (such as Lambda functions or APIGW endpoints). While the Lambda functions may be tightly coupled to these resources, they could be deployed within a separate CloudFormation stack to enable faster, safer releases.
Why do these semantics matter?
This all may sound like language nitpicking, but when someone is trying to structure their first serverless application, hearing these terms thrown around without qualification can be problematic. They may make incorrect assumptions about what you mean, so try to be as explicit as possible.
If you’re a language pedant like me and want to learn more serverless jargon (e.g. what’s the difference between an application and a workload?), then check out my Serverless Glossary article.
— Paul
Other articles you might enjoy:
Free Email Course
How to transition your team to a serverless-first mindset
In this 5-day email course, you’ll learn:
- Lesson 1: Why serverless is inevitable
- Lesson 2: How to identify a candidate project for your first serverless application
- Lesson 3: How to compose the building blocks that AWS provides
- Lesson 4: Common mistakes to avoid when building your first serverless application
- Lesson 5: How to break ground on your first serverless project