A reflection on how we improved our KYC procedures

BaiMao Shih
Xfers Engineering
Published in
4 min readSep 28, 2020

Know Your Customer (KYC) refers to the process of verifying the identity of your customers, either before or during the time that they start doing business with you. The KYC process is also a legal requirement intended as an anti-money laundering (AML) measure. Most financial institutions will implement some form of KYC measures to be compliant with local regulations.

Back in 2018 when I first joined Xfers, we were a small team of 20 engineers, with a small number of customers to serve and the KYC requirements were not as complex and varied.

As time went by, we experienced an increase in KYC requests that were submitted on a daily basis, with a list of growing requirements on KYC procedures to adhere to in different countries.

In view of the increasing number of KYC requests, we started focusing on answering a simple question - ‘How do we process a thousand KYC requests per day?’

We started with the low hanging fruits, opting not to revamp the codebase at first:

  • Hiring more KYC agents
  • Revamping admin page UI, enhance UX
  • Enhancing job rotation to prevent two agents processing the same user
  • OCR system for ID cards

Finally, we achieved the capability to process 5000 requests per day!

As we invited more companies on board, we realized that different companies have their own KYC preferences. For example, some retail merchants felt that World-Check One services are overkill for their business, so their users are considered verified right after completing our internal verification process.

In order to fulfil all these varied and specific requirements by different merchants, our codebase became messier as we wrote specific logic for each merchant. As a result, the whole verification process became increasingly harder to maintain.

As everyone on the team was still busy implementing feature requests for new merchants, no one had time to come up with a scalable structure that allows KYC requests to differentiate according to different merchants easily. Hence, our KYC system became undesirably complex over time…

Around the end of Q1 2020, we have decided that we have suffered enough from this situation, so we begin the PUPM(Per-User-Per-Merchant) project.

First, we realized that the processes in our KYC system were tightly coupled together as a whole. Such a huge system was not easy to maintain and even more difficult to extend it to incorporate future customisations. Thus we decided to break the system down into smaller modules, splitting it into several KYC sub-systems (Xfers VericationAI, IndonesiaIDCheckSystem, WorldCheck) where each sub-system has a clear entry point and handler.

Secondly, we implemented the concept of a “composable verification module system” which allows us to quickly figure out which KYC sub-systems are required for a particular merchant in question.

With this concept, we can

  • Easily skip sub-systems not required by the merchant during the KYC process.
  • Specify the documents that are required by the merchant in each verification module config. (declarative)
  • Adjust KYC flow for the merchant if they decide to skip certain sub-system in the future
  • Easily add any extra document if merchant request it in the future

In short, we turned a tightly coupled system with tons of if-else conditionals into a system that we can composed together in a functional manner to determine the state of a user’s KYC status for a specific merchant

Finally, we introduced a brand new way to determine a user’s verification status, using the UserVerificationStatusService. Back in the days, we were heavily reliant on the user’s flags to determine whether the user is verified.

The benefits:

  • Don’t need to worry about the discrepancy of the user’s verified flag, and clean bad data.
  • User’s status against different merchants could be different, all depend on the merchant’s KYC config, increase the flexibility of our system.
  • This service indicates why the user is not verified clearly, which sub-system is not qualified due to what specific reason.
  • Define the verified condition of each sub-system instead of twisting it for a specific merchant, this prevents lots of complexity in the codebase.

Summary

After completing the above project, the process of onboarding new merchant is considerably smoother, requiring less effort.

Taking Payfazz for example, which onboarded with Xfers at around Sept 2020. They have requested an extra check on an additional signature document which is not required by any other merchants. The changes needed to accommodate this request is just simply:

  1. Adding another document set and attaching it on a module config
  2. receive the document from an API
  3. show signature on the verification wizard

After these changes, we are ready to bring Payfazz onboard!

It is important to work on modular architectures as it reduces system complexities and also allows the system to be easily maintained and build upon. There’s still a lot more to improve on, however, it has already improved our life, tremendously.

I strongly felt that my efforts put into this project were paid off when I first used the new system to onboard a new merchant.

Thanks to User Team for putting in the hard work required for this project. I believe that we’ve taken a huge step in Xfers’ KYC history! I’m definitely looking forward to solving more pain points and play a larger role in Xfers’ success!

--

--