Any part of an application can be a bottleneck. At first, you may have issues with the infrastructure used by microservices, such as databases or message brokers. Scaling these parts is a complex concept, but here we will only touch upon the bottlenecks of microservices.
When you create a microservice, you may encounter problems with theĀ quantity of requests it can handle. It depends on multiple factors. You can use a concept such as the actors model to spread a load across threads and event loops.
If you have issues with CPU performance, you can create a separate worker that handles CPU-intensive tasks and schedules tasks with message brokers to achieve loose coupling, because you can add more workers at any time to handle more requests.
It you have I/O-intensive tasks, you can use load balancers to direct load to a specific service, but your microservice should be replaceable and shouldn't keep a persistent state, but can load it from a database. It allows you to use products such as Kubernetes to scale your applications automatically.
You should also split large tasks into small and separate microservices by logical domain. For example, create a separate microservice for handling accounts and another to render and show shopping carts in the online store. You can also add another microservice that processes payments, and they interact with each other with messages transferred by a message broker.
Let's create an application that can be scaled by running extra instances of some of its components.