In the previous part, we covered the challenges of the migration and my approach to address them. In this part, we’ll discuss the mappings of the endpoints and the schema with endpoint switches on client sides.
- Part I: Background of the migration and current state of the balance service
- Part II: Challenges of the migration and my approach to address them
- Part III: Mappings of the endpoints and the schema, client endpoint switches (this article)
- Part IV: How to execute dual-write reliably
- Part V: Architecture transitions, rollback plans, and the overall migration steps
Client Endpoint Switch
Let’s begin with the client endpoint switch.
There are only two write clients for the v1 balance. However, the number of v1 read clients has grown to over 20, with many client services directly calling specific v1 balance APIs.
To reduce the time and cost associated with this switching process, I’ve considered grouping multiple calls to the same v1 balance API under one wrapper service call.
For example, let’s say there are five client services that call the v1 balance GetX
API, and one of these services provides a wrapper API for the v1 GetX
API. This wrapper API Internally calls the v1 GetX
API and returns its response to the caller. In this scenario, we could switch the endpoints for all client services, except for the one providing the wrapper API, from the v1 balance to the wrapper client. See the following figure, which visualizes this transition:
With this approach, the number of endpoint switches will be reduced from five (for clients A to E) to just one (for client C) when switching from v1 to v2.
However, we need to dig deep into the following point more:
- Whether or not there is a wrapper API that can accept all types of request parameters specified by other clients and return all types of response parameters utilized by them
- If not, whether the client service team has available resources to develop it
v1/v2 Endpoint Mappings
After the migration, only the v2 API will remain active, while the v1 API will basically cease processing requests. Therefore, I summarized the mappings between v1 APIs and v2 APIs.
I organized these mappings into four types:
- v1 APIs mapped to existing v2 APIs
- v1 APIs mapped to new v2 APIs
- Unmapped v1 APIs
- Unmapped v2 APIs
The first type comprises the actual mappings of existing v1 APIs to their corresponding v2 APIs, while the second type refers to new mappings involving v1 APIs and new v2 APIs that will be developed in the future.
The last two types merit further discussion. Unmapped v1 APIs indicate those that will not be migrated to v2. I will elaborate on this later, but it’s important to note that some v1 APIs will indeed not be migrated. Unmapped v2 APIs represent newly introduced functionalities in v2; hence, there are no corresponding candidates in the v1 APIs.
As noted in the Current State section in Part I, the v1 API operates on a single-entry bookkeeping model, while the v2 API utilizes a double-entry bookkeeping approach. In other words, the v1 balance service supports only credit or debit transactions, while the v2 balance service can handle both. This raises a critical question: how do we address the missing side of the double-entry bookkeeping data in v2 when migrating from v1?
Thus far, I haven’t delved into the specifics of the v1 and v2 APIs. To better understand the technical issues at hand, let’s examine some details.
The v1 CreateUserBalanceAddition
API is used to grant a set of values to a user (or partner), essentially functioning as a debit operation in double-entry bookkeeping. Clients can specify M AdditionMethods
(debit) to indicate the types of values being granted, such as funds and/or points. The equivalent v2 CreateExchange
API requires clients to specify N Source
(credit) information and one Target
(debit) information.
However, the v1 CreateUserBalanceAddition
API client cannot specify the credit side in the v2 CreateExchange
request parameters because that information is not passed along by upstream services (recall that the v1 CreateUserBalanceAddition
API only accepts debit information). As a result, they will have to use dummy values.
While the v1 CreateUserBalanceAddition
allows for M AdditionMethods
, the v2 CreateExchange
is limited to N Source
and 1 Target
. If we map CreateUserBalanceAddition
to CreateExchange
, the M AdditionMethods
would only map to 1 Target
, which means CreateExchange
cannot accept multiple AdditionMethod
inputs.
Considering the available options to resolve this problem and their trade-offs, I advocate for enhancing CreateExchange
to accept multiple Target
information. By implementing this change, M AdditionMethods
could be mapped directly to M Target
entries, allowing the write client to maintain its current implementation with minimal adjustments.
We will continue to communicate with the payment service (write client) team to explore further solutions to this issue.
After the migration, most requests to the v2 balance service—except those that were originally made directly to the v2 balance service without switching endpoints—will involve either credit or debit information, as outlined in the mapping above. Future migration tasks will include a step to consolidate multiple single-entry bookkeeping requests into a single double-entry bookkeeping request, which will require the write client (payment service) to adjust its logic accordingly.
Similar to the accounting service migration described in the Alignment section in Part II, this task was considered but ultimately excluded from the scope. It would require considerable effort, especially because of the breaking changes involved in how accounting events are sent and reconciled after being converted into double-entry bookkeeping data.
v1/v2 Schema Mappings
As discussed in the v1/v2 Endpoint Mappings section, I have also organized the mappings between the v1 schema and the v2 schema into four types, similar to those in the endpoint mappings:
- v1 tables/columns mapped to existing v2 tables
- v1 tables/columns mapped to new v2 tables
- Unmapped v1 tables
- Unmapped v2 tables
An important note here is the need to match the primary keys (PKs) of v1 resources with those of v2 resources. Although I will explain the rationale behind this requirement later, adopting this policy will facilitate a smoother migration process.
In this article, we covered the mappings of the endpoints and the schema with client endpoint switches. In Part IV, we’ll discuss how to execute dual-write reliably.