Why do we care?
Speed wins in the market.
And this is no exception to modern software development. We want to be very agile in responding to customer requests and avoid re-deployment of the whole code base for every small change or fix. What is more, we do not want to put reliability of code at risk where any potential bug can bring the whole system down. And of course we want to scale our software development team fast where any developer joining the team can quickly understand the codebase and should not depend on any tribal or historical knowledge.
At idemeum we have chosen to build our passwordless identity platform leveraging Microservice-based Architecture (MSA). Our goal is to achieve high velocity in software development while ensuring scalability, availability, and resilience of our cloud infrastructure.
What is Microservice-based Architecture (MSA)?
Microservice architecture is a structural style that arranges an application as a collection of loosely coupled services.
Microservice is an independent, self-contained unit of software that implements a set of discrete, related functionality and enables strong modular boundaries with independent CI/CD and technology diversity. These services are designed to meet a specific and unique business need, for example: handling login, payment, verifying email, or sending notifications. This type of architecture is the opposite of monolithic architecture that is designed and built as a single coherent unit.
What are the benefits?
Let us first dig into the MSA advantages as compared to a classic monolith model.
- Smaller teams: engineering teams can be smaller and more targeted, each focused on autonomously managing, updating, and scaling a microservice. When onboarding new engineers there is no need to spend weeks figuring out how monolith works whereby increasing team velocity and removing learning curve barrier.
- Development flexibility: each team has a flexibility to choose technology stacks that best suit the need of the service and business capability they are developing. Exploration of new technologies and refactoring can be done incrementally as opposed to requiring “big-bang” changes.
- Deployment flexibility: teams can practice independent continuous integration and deployment of the business capabilities. With MSA a microservice can be updated without having to redeploy the whole application, making it easier to deliver small updates and changes.
- Flexible resource allocation: with MSA different services can have different availability requirements and have resources assigned based on criticality and business needs.
- Resilience: with MSA there is not centralized point of failure, and when a certain microservice goes down, the whole application does not stop functioning. Errors are isolated and are easier to remedy. We also believe that MSA is the architecture that provides a path to four 9s SLA with high internal SLO and SLI.
What are the negatives?
Let’s see what the challenges are as it relates to designing your application with MSA.
- Testing: having multiple microservices with complex communications paths and dependencies makes it harder to write tests.
- Overhead: MSA comes with some operational overhead. For instance, when developing microservices a loose coupling is desired, even if it means having code duplication. This issue can be mitigated by focusing on developing tools that can address functionalities across various microservices.
- Data challenges: microservices rely on a distributed data architecture where each service has its own isolated data store. Some business transactions will require updates to multiple databases, which will require setting up eventual consistency of data.
- Complexity: while each microservice is simpler, the overall system becomes more complex with time, especially with cross dependencies and communications paths.
How we designed idemeum microservices
Microservice definition and boundary should be defined by your business capabilities. Typically business architecture modeling is performed to map a business capability (something that business does to generate the value) to logical and physical components (how are where the business capability will be delivered). This business analysis exercise should guide the decision behind defining how many and what types or microservice the application will need.
Based on our experience we also adhere to the following technical principles when designing MSA:
- Single Responsibility Principle (SRP): microservices need to be cohesive and implement a small set of strongly related functions.
- Common Closure Principle: microservices must conform to a principle where things that change together should be packaged together in order to ensure that each change affects only one service.
- Independent data store: microservice doesn’t share database tables with other microservices.
- Thoughtfully stateful or stateless: whether it requires access to a persistence store or is it going to be a stateless service providing compute only processing.
- Data availability needs: data availability needs are accounted for – data distribution, data replication and understanding the impact to other microservices that rely on this new microservice.
Cross cutting concerns
Cross-cutting concerns are functionality areas that are implemented across the system and are shareable across microservices. At idemeum these concerns help us to develop new microservices in a fast way.
Pillars of observability
Observability is an attribute of the system that we built with the objective to make sure that when idemeum runs in production, operators responsible for it can detect undesirable behaviors (e.g. service downtime, errors, slow responses) and have actionable information to pin down root cause in an effective manner (e.g. detailed event logs, granular resource usage information, and application traces).
Test pyramid can be interpreted as relative number of tests that should be written at each granularity for every microservice. We ensure that our microservices automate the testing pyramid to deliver high quality software in fastest possible manner to our cloud.
Full cycle developers
At idemeum, we believe in “supporting what you build” philosophy. Developers own the responsibility of driving the feature from design to the support phase.
Resiliency and fault tolerance
Service Resiliency (interchangeably used with Fault Tolerance) is the concern that enables microservices with the ability of fault detection, isolation and graceful degradation. The microservice should be capable to withstand tough conditions and recover when conditions improve.
Microservice can be made resilient by using the below mentioned techniques or combining altogether:
- Circuit Breakers
- Rate Limiting
- Concurrency Throttle
- Throttling / Bounded Queues
idemeum deployment topology
idemeum deployment topology has no single point of failure and provides high availability and fault tolerance using the following AWS services:
- Virtual Private Cloud (VPC)
- Public and Private subnets
- Multiple Availability Zones
- Cross-AZ Load Balancer
- Internet Gateway
- NAT Gateway
- CloudFront / CDN