What Does Lola.com's Development Tech Stack Look Like?
How does Lola.com build the best corporate travel management software on the planet? It all starts with our stack.
At Lola.com, our goal is to build the simplest to use software for companies to manage all employee-driven spend.
We get a lot of questions about what tools, frameworks and languages we use to build the Lola.com platform, so we decided to dive deep into the ins and outs of our development technology stack.
Lola has a service-oriented architecture. Our user-facing applications (web and mobile) talk to a centralized "lola-server," which manages communication with a variety of specialized services which expose functionality for search, booking, scoring, secrets storage, messaging, analytics, and the like. All of these services are written in async Python 3, using the Starlette framework and we use a Python ORM called SQLAlchemy to manage queries to our (Postgres 12) database. We use the graphql dataloader pattern to improve the performance of returning objects to our front end applications. We use Elasticsearch for certain custom queries (most notably for our autocompletion endpoint for looking up specific hotels). We use redis as a performance cache and we use redis streams for streaming data between services and for lightweight job queuing.
Our user-facing web applications are written in React. We haven’t completely migrated every one of our components to React Hooks yet, but we’re close. We have a clean separation between business logic and UI which makes it easy for us to add new features. Our native iOS and Android applications are written using a lightweight React Native shell which hosts most of the UI in a webview. This gives us complete compatibility between our web applications and our mobile application while still allowing the mobile application to use mobile-specific features (such as integrating with push notifications or the device wallet) Our user-facing applications use graphql to talk to our servers.
We integrate with third parties over every imaginable channel. Some partners use SOAP APIs; some use REST/JSON; some use a secure FTP dropbox. We orchestrate our regular data feeds using luigi, Spotify's open sourced Python library for pipelining batch jobs. For all integrations, large or small, we are careful to construct a data model which we map the external data onto. (You can learn more about Lola.com’s integrations here.)
Because we deal with personally identifiable user information (also known as PII) and credit cards, we have to be extremely careful about how we handle this data. We have achieved PCI DSS Level 1 compliance through the use of a clever architecture. We segregate our "secret" storage into a single, highly secure data service which is directly accessible to only a few administrators. This service exposes an API that allows for only the writing of secrets as well as proxying requests to well-known endpoints which need them. Thus, when we need to send a credit card number to one of our partners, the proxy injects the credit card into the request as it is sent. At no point in the control flow does any of our client code ever see the secret thereby making it impossible for someone to hack our lola-server API to retrieve it.
Development Life Cycle
Lola has a mature software development life cycle. We make heavy use of Github's pull request features. Thus, you can't merge your code without a pull request. Your pull request is required to pass unit tests. And pass linting. Our Python code is required to be type annotated before it can be checked in. Depending upon the security level of the repository, a variety of code reviews may be required before your code can be merged. Once merged, we use continuous integration and continuous deployment tools to ensure that our staging environments (we have dev/staging/prod variants of each of our services, including our mobile applications) are always running the latest code. Everything runs on Amazon Web Services, deployed via Kubernetes. We monitor using X-Ray, pump our logs into sumo logic, and debug with Bugsnag and LogRocket.
15% of our development organization is dedicated to Quality Engineering, which is responsible for regular manual and automated testing. Quality Engineers participate in all phases of the life cycle, from requirements gathering through specs and mocks all the way to delivery. Quality Engineers maintain a comprehensive set of automated smoke tests which must pass before our code is promoted to production.
It’s impossible to overstate how important our development technology is to our final product, and to our company as a whole. Our mission to create the best possible corporate travel platform — and to constantly improve the technology behind it — means that we are always learning, testing, and integrating new tools.
Have a tool or technology you think we should be incorporating? Drop us a note in the comments below!