Once you get good at microservices...
... it will get crowded
Teams will focus more and more on building smaller apps
Clients don't want to know about all your microservices
They want an unified and easy to use API
- Centralized source of information
- Shared authentication and authorization
- Common call and error handling patterns
- Common communication format
But teams also want freedom to move at their pace
- Self service routing layer
- Full control over deployments
- Freedom to use different communication patterns when needed
We're at odds here
One side wants less change the other wants more
We need more Layers!
The API Gateway
Expose unified API to clients
Clients get one single API that hides the complexities about
knowing every single microservice that exists
Share common logic for backend services
Logic that can be shared across services (like authentication
and authorization) lives at the gateway instead of services.
Translate protocols and data formats
Be it legacy, monoliths or microservices, the gateway
can translate protocols and formats so that clients don't
have to know about it.
Hide backend implementation details
Killed the monolith or got a new microservice replacing
an old one? The gateway hides the details and clients continue
to behave as if nothing changed.
Classic proxy support
- Rate limiting
- Load balancing
- Service discovery
- Feature flipping
Many instead of one
Backends for frontends (BFFs) are just one API gateway
for every frontend you're serving.
You can build an API gateway as a GraphQL server and have
all your clients talk to it, hiding how the whole infrastructure
works as well.
How are we doing at DigitalOcean?
3 Rails monololiths
One shared rubygem with base code
Edge Gateway project starts
Starts serving production traffic
First all new microservice integrated
What is it?
- Internal DigitalOcean API gateway
- Built in Golang
- Implements shared features currently available at the monoliths
Monoliths and microservices
Microservices are building new functionality
and also slowly moving features out of the monolith.
Authentication and rate limiting happen at the gateway,
services receive the requests with metadata already filled in
and then perform the operation.
Applications don't talk to the gateway
Apps register themselves at the route management service
and the gateway talks to this service to figure out where to send
Gateway then forwards them the requests
Authentication and metadata is sent over HTTP headers
Headers approach removes dependency
Applications in any language can read the headers
and make use of then. They don't depend directly or
call the gateway to do their work.
Gateway or application updates
do not affect one another
What made most of the difference?
- Sane and easy to use defaults
- Free metrics and dashboards
- Self service solution
Where did we fail?
- Feature parity with existing monolith
- Being more direct in team-to-team communication
- Lack of guidance for teams without much Golang experience
- Better route validation and route wildcards
Are we ever going to kill the monoliths?