Earn Rewards: Sign up now and earn a special reward after your first deposit. See offer details



Save, invest, retire

GET — On the App Store


Concerned about market volatility? We've got answers and guidance for you. See videos


How We Built RetireGuide in R and JavaScript

We adhered to core product principles of immediacy and delight to problem-solve a complex programming project.

Articles by Steve Spagnola
By Steve Spagnola Published May. 11, 2015
Published May. 11, 2015
4 min read
  • We built RetireGuide by iterating between two programming languages.

  • We adhered to core product principles of immediacy and delight to problem-solve a complex programming project.

In this post, we’ll dive into some of the engineering that took place to build RetireGuide™ and our strategy for building an accurate, responsive, and easy-to-use advice tool that implements sophisticated financial calculations.

The most significant engineering challenge in building RetireGuide was turning a complex, research-driven financial model into a personalized Web application.

If we used a research-first approach to build RetireGuide, the result could have been a planning tool that was mathematically sound but hard for our customers to use. On the other hand, only thinking of user experience might have led to a beautiful design without quantitative substance.

At Betterment, our end goal is to always combine both. Striking the right balance between these priorities and thoroughly executing both is paramount to RetireGuide’s success, and we didn’t want to miss the mark on either dimension.

Engineering Background

RetireGuide started its journey as a set of functions written in the R programming language, which Betterment’s investment analytics team uses extensively for internal research. The team uses R to rapidly prototype financial simulations and visualize the results, taking advantage of R’s built-in statistical functions and broad set of pre-built packages.

The investment analytics team combined their R functions using Shiny, a tool for building user interfaces in R, and released Betterment’s IRA calculator as a precursor to RetireGuide.

The IRA calculator runs primarily in R, computing its advice on a Shiny server. This interactive tool was a great start, but it lives in isolation, away from the holistic Betterment experience. The calculator focuses on just one part of the broader set of retirement calculations, and doesn’t have the functionality to automatically import customers’ existing information. It also doesn’t assist users in acting on the results it gives.

From an engineering standpoint, the end goal was to integrate much of the original IRA calculator’s code, plus additional calculations, into Betterment’s Web application to create RetireGuide as a consumer-facing tool.

The result would let us offer a permanent home for our retirement advice that would be “always on” for our end customers. However, to complete this integration, we needed to migrate the entire advice tool from our R codebase into the Betterment Web application ecosystem.

We considered two approaches: (1) Run the existing R code directly server-side, or (2) port our R code to JavaScript to integrate it into our Web application.

Option 1: Continue Running R Directly

Our first plan was to reuse the research code in R and let it continue to run server-side, building an API on top of the core functions. While this approach enabled us to reuse our existing R code, it also introduced lag and server performance concerns.

Unlike our original IRA calculator, RetireGuide needed to follow the core product principles of the Betterment experience: efficiency, real-time feedback, and delight. Variable server response times do not provide an optimal user experience, especially when performing personalized financial projections.

Customers looking to fine-tune their desired annual savings and retirement age in real time would have to wait for our server to respond to each scenario—those added seconds become noticeable and can impair functionality. Furthermore, because of the CPU-intensive nature behind our calculations, heavy bursts of simultaneous customers could compromise a given server’s response time. While running R server-side is a win on code-reuse, it’s a loss on scalability and user experience.

Even though code reuse presented itself as a win, the larger concerns behind user experience, server lag, and new infrastructure overhead motivated us to rethink our approach, prioritizing the user experience and minimizing engineering overhead.

Option 2: Port the R Code to JavaScript

Because our Web application already makes extensive use of JavaScript, another option was to implement our R financial models in JavaScript and run all calculations client-side, on the end user’s Web browser. Eliminating this potential server lag solved both our CPU-scaling and usability concerns.

However, reimplementing our financial models in a very different language exposed a number of engineering concerns. It eliminated the potential for any code reuse and meant it would take us longer to implement. However, in keeping with the company mission to provide smarter investing, it was clear that re-engineering our code was essential to creating a better product.

Our process was heavily test-driven, during which product engineering reimplemented many of the R tests in JavaScript, understood the R code’s intent, and ported the code while modifying for client-side performance wins.

Throughout the process, we identified several discrepancies between JavaScript and R function outputs, so we regularly reconciled the differences. This process added extra validation, testing, and optimizations, helping us to create the most accurate advice in our end product. The cost of maintaining a separate codebase is well worth the benefits to our customers and our code quality.

A Win for Customers and Engineering

Building RetireGuide—from R to JavaScript—helped reinforce the fact that no engineering principle is correct in all cases. While optimizing for code reuse is generally desirable, rewriting our financial models in JavaScript benefited the product in two noticeable ways:

  1. It increased testing and organizational understanding. Rewriting R to JavaScript enabled knowledge sharing and further code vetting across teams to ensure our calculations are 100% accurate.
  2. It made an optimal user experience possible. Being able to run our financial models within our customers’ Web browsers ensures an instant user experience and eliminates any server lag or CPU-concerns.

More from Betterment

Recommended Content

View All Resources

WebValve – The Magic You Need for HTTP Integration

Struggling with HTTP integrations locally? Use WebValve to define HTTP service fakes and toggle between real and fake services in non-production environments.

How Does Betterment Calculate Investment Returns?

Understanding and using time-weighted and money-weighted returns within your Betterment dashboard.

Investing’s Pain Gap: What You Put Up With To Earn Returns

Markets are frustrating—especially when you look at a year’s worth of returns. Year to year, you can easily experience what we call the pain gap. The key is to not let the pain gap create a behavior gap between your account and market performance.

Explore your first goal

Cash Reserve

Our high-yield account built to help you earn more on every dollar you save.

Safety Net

This is a great place to start—an emergency fund for life's unplanned hiccups. A safety net is a conservative portfolio.


Whether it's a long way off or just around the corner, we'll help you save for the retirement you deserve.

General Investing

If you want to invest and build wealth over time, then this is the goal for you. This is an excellent goal type for unknown future needs or money you plan to pass to future generations.

See details and disclosure for Betterment's articles and FAQs.