In this post, we’ll look at why it sometimes make sense to buy new features rather than build them ourselves, and our key takeaways for other engineering teams who are weighing this decision.
At Coursera, we aspire to build technologies that lead to innovative pedagogical experiences and transformative learning. Most recently, the Partner Experience Engineering team has built several high-touch UI features on the course authoring platform to provide our partners with a better authoring experience.
With a small team of three front-end engineers, building any new feature always raised the question of the best approach — whether we should leverage third-party libraries or invest effort into building custom in-house solutions. We need to evaluate the tradeoffs with PMs and designers, with key emphasis on innovating technologies that are strategically important to Coursera.
Note that by “buying new features” we mean that we either bought a professional license or used an open-sourced third-party library for free. It is meant to convey using an external technology to solve a common problem so that we can focus on innovation.
The following sections will cover some cases why we chose to buy over build, and some examples of things we built and lessons we learned along the way.
Here are the arguments we came up with to support our decisions to buy over build:
- Focus on innovation: Leveraging existing technologies allows us to invest our time more strategically, focusing on innovation in the pedagogical space that contributes to our core competency, rather than wasting it solving a problem that’s already been solved by the developer community. We ship more and faster by not reinventing the wheel.
- Google-ability: Fellow developers can more easily build or debug issues in a third-party library, as they can use a search engine to find help. Chances are they are not the only ones facing the issue for that library.
- Maintainability: Well-documented libraries mean less documentation overhead on our end. No more relying on that one engineer on the team who “knows all the things,” which helps with improving the bus factor.
- Visibility in OSS: Buying gives us an opportunity to support and learn from the open-source community, giving ICs and the company more visibility in return.
- Familiarity for end users: The benefit of familiarity is less overhead of training users on a new feature. By using a popular library to accomplish a UI feature, we get the feature familiarity for free, since it is likely they have used that UI pattern some other place on the web before. The date picker discussed below is a good example of this.
Let’s take a look at some specific use cases where we leveraged external libraries and see what we learned from integrating them into our codebase.
1. Spreadsheet UI for Gradebook
The gradebook is a comprehensive feature that enables course instructors to view and edit learner grades. To empower instructors to manage this effectively for a large group of learners, we decided to create a spreadsheet UI, which would be familiar to instructors. Recreating an Excel-like experience with two front-end engineers in a quarter made zero sense, so we reviewed several external libraries and decided on Handsontable (HOT) with a pro license, which was the best fit for the set of features and degree of customizability needed to match our product spec.
What went well
- Powerful out-of-the-box features: HOT provided many complex features that were easily configurable, and saved us hours of time and effort we would have spent developing them ourselves.
- Helpful documentation: We found the docs and examples to be very thorough in explaining complex usages that were essential features for our partners.
- Test suites: The library had a comprehensive test suite, which in itself acted as a documentation of behavior when trying to read through the code. This also meant that when we contributed code to the library, we were being thorough with our testing and avoiding regressions.
- Learn about the team: We learned that the team maintained a Trello roadmap that was visible to contributors so we could see their upcoming improvements and plan our changes accordingly. We also learned that HOT had a small team of engineers working from a vastly different timezone, which meant they were resource-bound in reviewing feature requests and gave us some sense of their pace of work.
- Extending features was non-trivial: Although there was extensive feature support out-of-the-box, our spec required a custom UI interaction on the formula feature that extends a formula to multiple cells (something Excel supports, but not HOT). We found that adding this support ourselves was non-trivial, which was not immediately evident when reviewing the tool for viability. Make sure to evaluate your specs thoroughly and find places where extensions are needed and estimate development effort accordingly.
- Understanding external support: We had a paid license and were expecting support to be on par with that, but the support we got was only satisfactory. As the support team was small and located in a different timezone, they seemed overwhelmed by the requests they received from the open-source and paid communities. We sent a patch for a formula calculation fix that took a few weeks to get considered for review, and given our internal timeline had to make do with the fix for the time being. We are actively working with them to get the patch in so that the entire community can benefit from our work. We feel that we need to have more conservative expectations regarding external support, and estimate development efforts accordingly.
2. File Upload v2
Authoring a course involves uploading many assets such as videos, audio, and images, and a poor upload experience affects the productivity and efficiency of instructors trying to create high-quality content. Our existing solution was old, slow, buggy, and tangled external library code with implementation code, which meant contributing new code or switching out the external library was non-trivial.
This project involved mitigating all of those problems by migrating to Uppy, an open-source file uploader from Transloadit for the web. We already use Transloadit for uploads and encoding and we’re happy with their service, so we trusted their brand.
What went well
- Full upload flow right out of the box: File uploading “just worked” without us having to write much code on our end, allowing us to focus on our business logic instead.
- Faster upload times: This was crucial since lecture videos tend to be large and any improvement in upload time is beneficial.
- Happier users: The upgrade was very well received by our instructors, who are now able to upload large videos simultaneously and no longer worry when their computers go on standby during the uploads, because Uppy is smart enough to pause and resume correctly.
- Make your integration upgradeable: Our previous implementation of file uploads was deeply intertwined with the external library we were using. This made switching to a new library difficult since we had to untangle library code from implementation code. This was a large driver behind our switching wholesale to a new solution that we believed would be upgradeable. Having upgraded, we are in a better state now going forward.
- Support from an existing trusted provider is great: Since Coursera has been working with Transloadit as a customer for almost half a decade, we had a strong working relationship with them. Naturally this led to great support with fast turnaround times on any issues we had using Uppy or any bugs we found.
3. Date range selection UI for item availability
A new feature requirement was to make course items available for a certain period during a course session, so we needed a way to allow our instructors to author custom time periods.
This involved building a UI that consisted of two tightly coupled datepickers, one of which selected a range within a time period (the availability window for that item) while the other selected a single date within this selected range (the deadline date after which a late penalty would be applied). Additionally, this deadline date would also need to be displayed as a range if the instructor wanted an incremental late penalty policy spanning several days.
This behavior was complex enough for us to consider building something in-house, but given the abundance of external libraries available for the job, we instead worked with Product and Design to better understand the requirements and narrow down to the core possibilities that we could find a fit with while maintaining a desirable UX.
What went well
- Free: Complex features were freely and readily available in an open-sourced format, which is always great news for developers.
- Quick support: The author of that library was very responsive in answering our questions on their forum, which kept us moving forward while developing.
- Matching product spec exactly to an external library is hard: Given the complex UI interactions necessary for this feature, we had to ruthlessly prioritize core design requirements while maintaining functionality to get the feature out the door in time.
- Keep stakeholders involved early: When reviewing the available external libraries, make sure to keep the PM and designer in the loop, so as to waste minimal time and effort in building sub-optimal solutions. Having these stakeholders involved early meant we could quickly iterate over multiple libraries before choosing the best fit, especially when trying to match spec with an external library.
- Solidarity: At Coursera, we encourage solidarity and this project was an exemplar of that value.
Now that we’ve covered lessons specific to our use cases, let’s take a look at some high-level lessons that can apply to buying externally in general.
- Investigate Github and the team: Probably one of the biggest things we realized from our process was that before investing in a license or even a free trial, one should research the library’s Github page for things like the number of open issues versus open PRs, size of the team actively working on it, and more importantly how responsive they are to requests. Also check how big the engineering and support team is, as this will set the right expectations when requiring assistance. We learned that only looking at documentation for feature support may not provide a full perspective on the developer experience. We believe these are helpful red flags when choosing between libraries, especially when paying for a service.
- A11y: This was not specifically an issue for us, but something we want to point out as a heads up. As the Internet continues to grow and touch a larger demographic, we have to consider whether a library’s UI provides web-accessible markup. A really powerful library that lacks accessibility, or even worse, displays anti-accessible patterns, can severely hurt the user experience.
We have learned a lot from our decisions to buy over build, and we do not regret making these decisions. We are, in fact, positive these lessons will guide us better in the future as we keep innovating and solving challenging problems using external libraries when that is the best solution.
We’d also like to add that we have covered only use cases that directly affected the UI of our product. Lots of NPM packages deal with non-UI behaviors, and the lessons learned here may or may not directly apply.
At Coursera, we are always eager to learn and better ourselves, so we’d like to learn from you as well — what are some challenging decisions you have made and lessons you learned?