Enhancing Mobile Check Deposits

By Eric Ying, Software Engineer at Chime

At Chime, we provide our members with multiple ways to transfer funds, one of which is Mobile Check Deposit (MCD). MCD is how our members deposit physical checks into their checking account by taking pictures of the front and back of the check using the Chime app. Despite the growing prevalence of digital payments, paper checks still remain the second most common form of wage payment behind direct deposit. According to PayrollOrg's 2024 Getting Paid in America survey, 3.68% of participants responded they were paid in paper checks, only behind the 91.9% for direct deposit (source). The Cash and Checks team at Chime is responsible for building the entire end-to-end experience of MCD —from in-app submission to secure movement of funds behind the scenes.

Like most features on Chime, MCD relies on communication between the front end (the mobile app in this case) and backend microservices. In the past, when a check was submitted, the app would make a single backend call to our service. In that single submit call, several operations were performed on the check back-to-back:

  • Store relevant check metadata in our database.

  • Run various risk rules against the check.

  • Perform optical character recognition (OCR). This step is particularly important, as it is how we extract the account and routing number from the check.

  • Send checks downstream to be processed.

In 2024, we undertook a large-scale migration to improve this process by splitting the single submission API call into three lightweight API calls: those being Upload Front Image, Upload Rear Image, and Submit.

  • Upload Front Image: This is called immediately after the member uploads the front image of the check.

  • Upload Rear Image: This is called immediately after the member uploads the rear image of the check.

  • Submit: This is called when members review the check and tap submit.

There were three primary motivations behind this migration:

  • Access check information prior to check submission: By decoupling OCR from the submit and moving to the front image upload, we can begin validating check details earlier in the process, which unlocks opportunities for smarter processing decisions later down the line. This opens the door for future improvements that critically rely on this data. One example is instant release of check funds, an initiative launched shortly after this migration to immediately release funds for the majority of checks deposited on Chime.

  • Enhance check delivery estimates: The ability to access check information earlier enables us to give a smarter estimate of check hold duration, or how long before we release funds to the member.

  • Provide feedback in real time: Members often take photos of checks in poor conditions, resulting in unreadable check images. When this happens, we prompt members to restart the MCD process, leading to a poor member experience. With multi-step submission, we can alleviate this pain point by delivering real-time feedback on the quality of the image immediately after each attempt.

Pre Migration

[CC] Enhancing Mobile Check Deposits - Content Image 1

Post Migration

[CC] Enhancing Mobile Check Deposits - Content Image 2

Switching from REST to GraphQL

To facilitate communication between the mobile app and backend, we adopted GraphQL, a widely used data query language. Switching from traditional REST endpoints to GraphQL brought several key advantages, including improved readability through a strict in-built typing system and a more flexible schema that allows addition of new fields without breaking app compatibility.

For our implementation, we chose to map each step of the submission – upload front image, upload rear image, submit – to separate GraphQL mutations (A GraphQL mutation is any operation that modifies server data in one form or another). Internally, we created a check deposit record in the first upload front image call and updated that same record in all subsequent operations. In order to link multiple API calls to the same check deposit record, we introduced a new field, submission_uuid, to each mutation's input. This UUID would be generated by the front end, passed to our backend service, and used to reference the appropriate database record.

[CC] Enhancing Mobile Check Deposits - Content Image 3
[CC] Enhancing Mobile Check Deposits - Content Image 4

Propagating Errors to Frontend

One key decision we had to make was how to clearly communicate downstream errors to the app. Failures could occur at various points in the submission lifecycle, some of which are caused by unclear images, while others are caused by unexpected system issues like timeouts and exceptions. Regardless of the cause of the failure, it is important that we clearly communicate these issues to members to provide a more transparent, positive experience and reduce unnecessary support inquiries.

We decided to create a standardized error object meant to encompass all relevant information for member-facing UI, namely the error message, button text, and associated button action. The fields in this object were populated by the back-end server depending on what error was raised. We implemented a standardized way to return actionable error messages via GraphQL unions, improving transparency and reducing unnecessary member support inquiries. By controlling the error UI in the backend, we could modify the error string or UI behavior on the fly without needing to wait for a mobile app release.

[CC] Enhancing Mobile Check Deposits - Content Image 5
[CC] Enhancing Mobile Check Deposits - Content Image 6

Transmitting Check Images

Another consideration in our migration was determining the method of transmitting images of the check from the app to the backend. We evaluated two main approaches, each with its pros and cons.

The first involved passing the Base64 encoded version of the image directly into the request object. This was the most straightforward but came at the cost of increased payload size.

The second leveraged Amazon S3 to upload an image to an intermediate bucket in the app. Once the image was uploaded and validated, an async event notified our backend service to retrieve it and process it.

Option 1: Direct send

[CC] Enhancing Mobile Check Deposits - Content Image 7

Option 2: Async upload to S3

[CC] Enhancing Mobile Check Deposits - Content Image 8

Ultimately, we settled on the former approach, as it involved the least amount of additional dependencies. It also did not introduce any async workflows, which would further add complexity to the system. The downside of increased payload size could be mitigated by compressing the images to a predetermined resolution and quality, thus keeping the sizes of the payloads relatively constant.

Conclusion

This migration was rolled out over several weeks, with careful monitoring to ensure no regression was introduced. Early signals showed positive results:

  • ~0.75% increase in MCD completion rate.

  • ~5 seconds reduction in average MCD completion time.

  • A reduction in check hold rates due to smarter hold policies made possible by this migration and written by our risk team. A direct benefit of this is a decrease in member contact rates and an increase in member satisfaction.

  • A smaller benefit was the opportunity to refactor and clean up thousands of lines of legacy code across multiple services, significantly reducing tech debt.

  • Most importantly, this migration laid the groundwork for several enhancements to MCD, ensuring that Chime is well-positioned to adapt to a changing financial landscape.

Mobile Check Deposit is a feature that most major banking apps support nowadays – as such it is often taken for granted. Behind the scenes, it is a complicated system that must strike a delicate balance between risk mitigation and member experience. This migration was able to positively impact both ends of the spectrum – something that is rare. By leveraging check data more effectively, we unlocked new opportunities for informed decision-making while also enhancing the member experience via real-time feedback and faster turnaround time. This is just one of the many examples of Chime's commitment to member obsession.