Designing a Zero Downtime Migration Solution with Strong Data Consistency – Part III

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.

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:

Fig. 10: Switching endpoints from v1 balance to the wrapper client

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:

  1. v1 APIs mapped to existing v2 APIs
  2. v1 APIs mapped to new v2 APIs
  3. Unmapped v1 APIs
  4. 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.

Fig. 11: Summary of CreateUserBalanceAddition and CreateExchange

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:

  1. v1 tables/columns mapped to existing v2 tables
  2. v1 tables/columns mapped to new v2 tables
  3. Unmapped v1 tables
  4. 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.

  • X
  • Facebook
  • linkedin
  • このエントリーをはてなブックマークに追加