Moving Fast by Moving Slow: How We Built Payments at Ramp

A deep dive into why investing in scalability, reliability, and extensibility from Day 1 embodied our mantra of velocity at all costs.

Shreyan Jain
32 min readadvanced
--
View Original

Overview

The article discusses Ramp's approach to building a new payments platform, emphasizing the importance of taking a slower, more deliberate approach to ensure long-term scalability and maintainability. It highlights key design principles and lessons learned during the development process, showcasing how thoughtful architecture can lead to greater product velocity in the future.

What You'll Learn

1

How to design a payments system that scales with future needs

2

Why decoupling business logic from payments logic is crucial for scalability

3

When to prioritize API-first design principles in fintech applications

4

How to implement a reliable task queue for payment updates

Prerequisites & Requirements

  • Understanding of payment processing systems and APIs
  • Experience with backend development and database design(optional)

Key Questions Answered

What are the key design principles for building a scalable payments system?
The article outlines several design principles, including decoupling business logic from payments logic, creating flexible data models, and implementing API-first design. These principles are essential for ensuring that the payments system can accommodate future growth and diverse use cases without incurring high technical debt.
How did Ramp improve the reliability of their payments processing?
Ramp modernized their payments stack by integrating with JPM's ACH transfers API, which allowed them to bypass outdated NACHA file generation. This shift enabled them to use standard API features like idempotency keys and webhooks for real-time updates, significantly improving reliability and reducing errors in payment processing.
What challenges did Ramp face with their legacy payments system?
The legacy system was brittle and error-prone, relying on outdated NACHA file formats and manual processes for payment initiation and tracking. This resulted in issues like failed transfers due to simultaneous connections and a lack of visibility into payment statuses, which hindered operational efficiency.
Why is it important to avoid nullable columns in data models?
Nullable columns can complicate data integrity and lead to confusion in future maintenance. The article suggests using joiner tables instead, which provide clearer relationships and reduce the risk of errors in data handling, ultimately leading to more robust data models.

Key Statistics & Figures

Time to launch new products
Less than 1 week
Onboarding a product onto the new payments service has taken less than 1 week since implementing the final PaymentRequest refactor.
Delay in launch due to rebuilding payments service
~2 months
Rebuilding the payments service from scratch pushed back the launch date by approximately 2 months, but was deemed necessary for long-term scalability.

Technologies & Tools

Some links below are affiliate links. We may earn a commission if you make a purchase.

Backend
Jpm
Used for ACH transfers and payment processing integration.
Backend
Celery
Used for asynchronous task processing and managing payment update notifications.

Key Actionable Insights

1
Invest time in designing flexible data models that can accommodate future use cases.
By creating data models that are not overly specific to current needs, you can prevent costly refactoring in the future as your application scales and evolves.
2
Implement API-first design principles to enhance reliability and user experience.
An API-first approach allows for better abstraction of complex processes, making it easier for users to interact with your system without needing to understand its internal workings.
3
Utilize a reliable task queue for processing payment updates to ensure consistency.
Building a custom task queue can provide better control over how updates are processed, preventing issues like double processing or missed updates that can occur with less reliable systems.

Common Pitfalls

1
Relying on outdated systems and processes can lead to significant operational inefficiencies.
The legacy payments system at Ramp was fraught with issues due to its reliance on manual processes and outdated file formats, which created bottlenecks and increased the risk of errors.
2
Failing to design for extensibility can result in high technical debt.
Ramp's initial payments integrations were built with specific use cases in mind, leading to a system that was difficult to extend. This highlights the importance of considering future needs during the design phase.

Related Concepts

Payment Processing Systems
API Design Principles
Data Modeling Best Practices
Scalability In Software Architecture