Microservices Architecture

Microservices Architecture

Definition

Microservices Architecture is the decomposed system architecture adopted by ICMP, splitting platform capabilities into multiple independently deployable and scalable microservices that collaborate via APIs and message queues. The microservices architecture ensures high system availability, elastic scaling, and rapid iteration, and, together with Multi-Region deployment and Region Failover disaster recovery, supports global 7×24 services.

Architectural Features

The characteristics of microservices architecture include: Service Autonomy—each service is independently developed, deployed, and scaled, and technology stacks can differ; Loose Coupling—communication via REST, gRPC, and message queues reduces dependencies; Elasticity—failure of a single service can be isolated without affecting the whole system; Scalability—high-load services can be horizontally scaled as needed. Typical ICMP microservices include: Card Management, Billing, Usage Aggregation, API Gateway, Notifications, Reports, etc.

Relationship with High Availability

Microservices architecture supports Multi-Region multi-region deployment: each region independently deploys all or part of the services; combined with Region Failover, traffic switches to other regions in case of a single-region failure; combined with Failover, load balancing, and health checks, high availability is achieved. The platform is exposed externally uniformly through API Gateway, and internal service-to-service communication is done via service discovery and load balancing.

Practice in ICMP

SimtoLink ICMP adopts a microservices architecture, with independent services for each business domain; supports Multi-Region and Geo-Distributed deployment; combined with Region Failover to ensure high availability; provides capabilities externally via RESTful API and Event Subscription; supports agile iteration and independent release.

Data Ownership after Services Are Split

In connectivity management, a microservice architecture splits SIM lifecycle, usage, charging, notification, and the external API into services that can be released on their own, then cooperates through synchronous calls or messages. The point of the split is that a fault and a release are not tied to the same process. It is not that every fact has several authoritative copies. Each kind of fact has one owner: SIM state is maintained by the SIM service, CDRs are received by the usage service, and invoice amounts are calculated by the charging service. Other services may keep a copy for queries, but an expired copy must be able to say that it is not the authority.

Split this way only when the boundaries are already stable and the team can deploy and observe each service on its own. If provisioning, charging, and notification are still changed by the same people in the same release, several processes only add points where a call can fail. A cross-service action needs a clear definition of done. Provisioning has succeeded when the carrier side has accepted it and the SIM service has recorded it, not when the notification service has sent the email. Network state exchanged with the operations support system, and orders exchanged with the business support system, should not be written into one service’s private tables and then updated by direct writes across those tables.

An Independent Deploy Does Not Close the Books

A common error is to believe that once each service scales on its own, usage and invoices naturally agree. The usage service can receive a CDR before the charging service has consumed the message. Traffic on the portal has already increased, and the charge is still the old one. Showing that short gap as a “live invoice” makes the customer think the debit is wrong. Another error is a distributed transaction that locks every service together. If any downstream slows down, the provisioning API fails entirely, and the isolation the split was meant to provide is cancelled.

A shared database breaks the boundary in the same way. If the charging service writes the SIM service’s tables directly, the SIM service cannot tell, at release time, which fields someone else still depends on. A retry after a timeout that carries no idempotency key executes the same suspension twice, and the state flickers. When designing microservices, give every cross-service message an owner, a retry ceiling, and a reconciliation method. Independent deployment should serve release and fault isolation. It should not manufacture several ledgers that contradict one another.

Release order also follows data ownership. Upgrade the consumers of a read-only copy first, then the service that owns the authoritative data, so an old process is less likely to write a new field as empty. A rollback cannot roll back only one service either. An amount the charging service has already written under the new rule must not be overwritten by an old version of the SIM service back to the previous state. Each service’s health check should verify that it can read its own authoritative store, not only that the process is still listening on a port.

A cross-service write must be able to say how far it got. If provisioning changes SIM state, then notifies charging, then pushes to the customer, a failure in the middle must show whether charging heard it. Compensation can finish the remaining steps, or it can put the SIM state back and tell the caller it failed. It cannot leave both results in place. Each step uses the same business identity. On retry, that identity recognizes steps already finished, so a notification is not sent twice while the state was changed only once.

Define a field change first in the service that owns the data, then tell the consumers. A new field a consumer does not yet understand should be ignored, not fail the whole message. Before an old field a consumer depends on is removed, confirm that no service is still reading it. Writing a shared table directly skips that process, and at release time nobody can tell who will still read the old column. When observing each service, it should be possible to see how many messages it has not yet processed. That backlog is itself the reason usage and the invoice disagree for a while.

Fault isolation means that when a downstream is slow, the upstream has an explicit timeout and a way out. An API that queries usage may return “temporarily unavailable.” It should not drag SIM provisioning down with it. Steps that truly must succeed together should be written in the authoritative data of one service. Do not pretend to split them and then tie them again with a remote lock. Whether the split is sound is whether a SIM’s state still has exactly one owner.

Related Terms

Return to International IoT Cloud Platform Terminology