PayMongo recently launched a redesign of its know-your-customer (KYC) form to help bring the next 100,000+ PH businesses online.
We have seen explosive growth in the past year, thanks in no small part to the self-service funnel carved out by our KYC Form. While other payment platforms require that their customers go through an onboarding process via email or submission of physical documents, PayMongo empowers its users to complete and submit their application through our website so that they can begin receiving payments without the tedious back-and-forth of speaking with a sales agent.
This approach has enabled us to onboard thousands of businesses in less than 2 years.
Our original KYC Form got us 95% of the way in terms of compiling complete applications, but in order to fully close that loop and refine the overall experience for our new users, the Product Engineering team rolled out this latest iteration.
While those two primary goals were the driving force behind this release, the Engineering team also saw room to improve the codebase in ways that could make a tangible impact on our users. We used mostly the same tools and technologies, but we were more judicious about how we used these to deliver a new experience.
Take async/await syntax, for example—writing asynchronous code used to be an exercise in indentation:
But with async/await, we can write all that as if each line were to execute synchronously. No need to think about sync and async code paths in the same function! The execution flows linearly from top to bottom.
However, all these new bells and whistles don’t come without a few subtleties. We need to be careful about applying await, especially when dealing with more than one asynchronous operation at a time, like multiple network requests.
Our KYC Form needs to query multiple endpoints to load completely, so our old code used to look something like this:
Seems innocent enough. But this approach was inherently slow because we were queueing requests that are completely independent of one another! Data Batch B didn’t need to wait for Data Batch A to finish before starting! Neither did Data Batch C need to wait for Data Batch B.
But this is exactly how await works. The next lines of code aren’t executed until what you’re await-ing finishes completely. Instead, we should be executing all the requests in parallel to retrieve all the data much faster than if we were to initiate the requests one after another.
We can still use await to do this, but to execute all these in parallel, we could take advantage of a greatly underutilized method in the Promise API: Promise.all().
Promise.all() accepts an array of promises and returns its own promise that will resolve once all the promises it is given are fulfilled. Therefore, await-ing it guarantees that (1) all requests will be complete with their corresponding data in the succeeding lines of code and (2) those requests will be initiated all at once.
Keep in mind that each item in the array needs to be a promise, so we shouldn’t be await-ing them before passing them into the Promise.all() call. Otherwise, we’d end up right where we started.
This simple change resulted in our new KYC Form loading more than 2.5× faster than before: down to an average of just 1.5 seconds from 4.0 seconds! All with a single wrapping Promise.all() call.
Hopefully, this little performance boost—and the new and improved form UX—pushes more of our users to complete the onboarding process and join the thousands of businesses already accepting payments online with PayMongo.
To the next 100,000+ businesses! 🚀
Miguel N. Galace is a Software Engineer at PayMongo. This article was originally published on Medium on September 8, 2021.
Visit https://jobs.lever.co/paymongo/ for job opportunities and internship programs at PayMongo.