Asana’s Tech Stack: How we build a collaborative app for teams of all sizes

Asana Engineering TeamEngineering Team
February 28th, 2022
3 min read
facebookx-twitterlinkedin
Engineering article banner image

I talk to a fair number of software engineers about working at Asana. They’ve usually heard a lot about how it’s a great place to work, and they want to know more about the tech stack and the challenges we work on.

In the spirit of highlighting the technical challenges that have kept me excited since I started working here three years ago, I wanted to share an overview of our current architecture along with some of the problems we’re working on today.

About the product

At Asana, we want to make teams of any size (1 to 100,000+) more effective by organizing their work in a single connected tool. This drives our product roadmap, along with our architecture and its challenges.

At most companies, each team has their own work-tracking tool (think JIRA for Engineering, Zendesk for Customer Support, Salesforce for Sales). If people didn’t have access to another team’s tool, they’d have no idea what was being worked on, who was working on it, or why it mattered. Anyone working with multiple teams would have their work scattered across multiple tools with no guarantee each one was up-to-date.

In contrast, Asana believes that every team in a company should be using the same tool to track (or sync) their goals, projects, and tasks. This shared source of truth gives everyone clarity about who’s working on what, by when, and why—without the headaches of switching between tools and information silos.

This motivates some architectural requirements:

  • Feature-rich and flexible enough to support the plans and workflows of teams as different as HR, Engineering, and Sales

  • Performant, reliable, and synced across multiple devices so users stay focused on their meaningful work (not “work about work”)

  • Easy for users to learn and set up their workflows

  • Integrated with a wide range of team-specific and company-specific tools

  • Secure & scalable enough for organizations of 100,000 and beyond

Add all these factors together, and you have a software suite with challenges across the stack!

Asana’s Work Graph data model

One of Asana’s product differentiators is the flexibility and number of connections that users can create in the data model. Almost every object can be “multi-homed” into other objects, creating a dense graph of objects and relationships.

This presents constant challenges around feature scaling, data integration, and product modeling.

As an example, users might have read access on a particular task for many reasons. They could be the task’s assignee, they might be in the task’s collaborator list, or the task might be public, or they might be a member of one of the task’s projects, or they might be a member of a team associated with one of those projects. It’s important to have the right data permissions and controls in place, but standard approaches to SQL queries wouldn’t be able to run this logic performantly.

To address these challenges, we’ve built a MySQL-backed persistence layer called OKVStore. It’s inspired by graph databases and object-oriented languages and enables engineers to declaratively define their properties & access control rules in an object-like configuration file without worrying about the object-relational impedance mismatch or LunaDb’s reactivity pipeline (more on that below).

Of course, we still have many challenges in this space that keep us busy:

  • Supporting divergent use cases like content calendars, ticket backlogs, and sprint-planning in a single tool

  • Mapping the data model to team-specific productivity tools

  • Modeling team relationships in matrixed organizations

  • Data pipelines for replicating to Elasticsearch and ML datastores

  • Integrating data governance into our frameworks

  • Scaling to multiple clusters distributed across the globe

Rich frontend clients

To support the wide variety of features users expect to get their work done, Asana’s codebase has grown to millions of lines of TypeScript/JavaScript code and thousands of React components.

To keep the quality of the product and pace of development high, we’ve been working on several challenges:

  • Flexible spreadsheet, calendar, and timeline views for planning big projects

  • Richtext document editing for kicking off projects & keeping notes

  • Extracting a library of accessible React components across dozens of teams

  • Integrating Bazel for speedier incremental builds & test runs

  • Automating releases and rollbacks based on error reporting

  • Bundle-splitting to speed up page loads

In addition to all this web code, we also have mobile apps written natively in Swift & Kotlin and an Electron-based desktop app.

Realtime backend

Users expect that when they add a comment on a task in Asana, every other browser will immediately show that comment without needing to refresh the page. This could be straightforward to build for a single comment feed, but becomes a lot harder when users expect the same reactivity from every feature in the app (even for edits that fan out to thousands of connected clients).

Asana built a custom service in Scala called LunaDb to power this app-wide reactive data-loading. Clients issue queries for graphs of related data and business logic calculations (similar to GraphQL), automatically subscribing to any updates to those query results. LunaDb then watches for changes in the underlying databases and pushes query updates down to all subscribed clients.

Writes are also routed through LunaDb, executing in our Node-based LunaServer backend application framework.

Asana first introduced this technology in 2015 (around the time GraphQL became public) and it’s going through a renaissance to meet our newest challenges:

  • Refactoring LunaDb to support more backend languages for product developers

  • Isolating stateful and stateless components for scalability and modularity

  • Instrumenting requests with distributed tracing to give developers insight into costs

  • Migrating to GraphQL’s query format

  • Bringing reactive data-loading to mobile clients

…and we’re hiring!

Asana’s been around for 14 years and it feels like we’re just getting started. We have an ambitious vision full of new problems we’re excited to solve and a strong foundation of a well-loved product.

There’s a lot of opportunity to bring new technical knowledge to Asana, solve these challenges, and learn from the smart & kind engineers already on the team. (In addition to technical excellence, we also pride ourselves on our culture of design docs, close-knit teams, tech talks, and work-life balance)

If any of this is exciting to you, we’re hiring for engineering roles across the stack. Check out our open roles.

Related articles

Role Spotlights

Why Asana is switching to TypeScript