Story of a Startup Part 2: Bringing GraphQL to HyreCar

Trevor Heath


This is a post on how GraphQL gave HyreCar the speed and stability to scale.

*This post is a continuation of our series about paying down technical debt and Novvum’s re-architecture of the Hyrecar platform. You can read the introductory post here*

As mentioned throughout this series, 2018 is the year Novvum’s team was tasked with building a new scalable architecture for Hyrecar. The new architecture needed to bolster performance & functionality while also providing a comfortable developer experience for the Hyrecar engineering team.

This article will dive into our implementation of GraphQL assuming most readers are familiar with the query language.

Sample of GraphQL request using GraphQL Playground

Implementing GraphQL at HyreCar

The idea of bringing GraphQL at HyreCar began taking shape after internal announcements of an IPO had been announced in early March. We had less than 60 days to migrate HyreCar’s entire technical infrastructure.

One of the many issues surrounding the stability of the platform were traced back to one of the two client side applications. The user-facing React client would only see downtime when the legacy REST api would go down. The other, an admin application used internally was concerning in the way it interacted with HyreCar’s data.

Direct SQL injections...

Undoubtedly a cardinal sin in development. On top of the potential security, data integrity, and stability concern with the admin application, a large number of untested features were piping into production everyday.

With GraphQL, we were able to untangle all of our client applications with the new backend services. The benefits of having an abstraction layer interfacing with our data resulted in a drastic improvement

Legacy Admin SQL Injections

GraphQL Abstraction decoupling data and client relations

A Serious Case of Mono… repo

How we organize our codebase will greatly impact the effectiveness of our engineering team in meeting HyreCar’s business needs. We chose to build the API in NodeJS paired with TypeScript since the best support for GraphQL is still dominated by the JavaScript ecosystem and community.

The codebase also had to be organized in a way that would reduce conflicts arising between HyreCar divisions. Each division was accustomed to petitioning for changes to the codebase to meet their respective goals. Therefore, it made sense for us to have a monorepo of self-contained services for each function of the business. Each service would manage its own data and business logic.

To make this work, each service would need its own GraphQL schema. We could then combine these individual schemas using schema stitching and graphql bindings (shoutout to our folks at Prisma) into a single gateway. This gateway would be responsible for orchestrating different cross-service functions necessary to perform platform-specific tasks.

[Example of Booking a Car Mutation]

For example, booking a car would involve the Users, Rentals, Cars and Payments services.

[folder structure image here]

The file structure of each service is standardized as such:

  • database: We use Prisma which provides a GraphQL abstraction layer on top of
    HyreCar’s MySQL servers. We can integrate prisma directly into the service’s schema and use prisma-bindings to easily implement business logic.
  • resolvers: This is where we implemented our graphql schema and resolvers for the service. It extends the schema generated by Prisma with custom fields which are not in the database as well as mutations specific to the service (like taking payments, communicating with external insurance services, etc.).

We rely heavily on Apollo Engine to provide us with useful insights on how our schema is performing against client requests. Bringing us oversight to particular queries and/or fields that take longer to resolve. Thus giving us the ability to strategize ways to speed up the site. On top of that, access to a number of cool features like caching, persisted queries and many more.

We’ll explore these concepts more in depth in our future series articles.

Key Learnings

At the end of the longest 60 days of our lives, GraphQL proved to be the right choice for HyreCar giving them the much needed iterability, development speed and stable infrastructure to set stage for a successful IPO.

HyreCar’s engineering team have been pleased with the more intuitive contract forged between frontend clients and backend services. Waiting for backend engineers to implement a new endpoint or modify an existing one is a thing of the past for HyreCar’s frontend engineers. Meanwhile, backend engineers can rejoice on the stability and specificity of GraphQL. Concentrating their efforts on maintenance and improving comprehendable interfaces.

A major pitfall we avoided through the guidance of the Apollo team was trying to deploy each service individually on its own server. Doing so would have introduced a significant amount of performance losses and operational overhead.

The following article by DHH sold us on the idea of keeping our code in one place:

As of today, our newly implemented GraphQL APIs have been in production for over 5 months. With amazing tools and support from companies like Apollo and Prisma,  the difficult and daunting challenge became manageable.  However, it doesn’t stop there,  the tools and foundation in place have also continued to provide the insight necessary to recognize performance issues and continuously improve HyreCar’s platform.  Data from Apollo Engine drives decision making as we add features and functionality to improve user and developer experience. Stay tuned for more articles from us about this project and our journey.