How Airbnb Supports Co-Hosting

Angeline Rao
The Airbnb Tech Blog
11 min readDec 9, 2021

--

A deep dive into Airbnb’s collaborative hosting infrastructure

By: Angeline Rao

Introduction

Airbnb’s mission is to empower Hosts to deliver one-of-a-kind stays that make it possible for guests to experience the world in a more authentic and connected way. Sometimes hosting is handled by one person, but in many cases hosting is a group effort. Hosts often share their responsibilities with another trusted person, such as a family member or a neighbor. These trusted partners are Co-Hosts on the Airbnb platform who are granted access to the Host’s listing, reservations, and messaging with guests.

Co-Hosting is just one form of Host collaboration. As hosting has become mainstream, the scale of hosting has grown as well; in fact, many people now host on Airbnb as their primary occupation. From Host entrepreneurs running their own businesses, to Hosts that are part of established hospitality companies, these types of Hosts collaborate through a Team on Airbnb. Within a Team, hosting team members are granted roles that correspond to their real world hosting responsibilities (e.g., guest manager) and have a set of corresponding permissions (e.g., permitted to message guests).

As the number of collaborative Hosts grows and new forms of collaboration get introduced, the engineering work to support them becomes increasingly complex. With this challenge in mind, Airbnb has developed a single common infrastructure that can support all current and future Airbnb collaboration products. This solution is now available for all internal teams.

In this blog post, we will cover the unified architecture of collaborative hosting at Airbnb and how we use this shared infrastructure to streamline the process of building products for Hosts. In the next section, we will illustrate why supporting collaborative hosting without a shared infrastructure quickly became unwieldy. Then, we will walk through Airbnb’s architecture for collaborative hosting. Finally, we will discuss how this infrastructure supports the needs of product engineers.

Background & Motivation

Before we jump into collaborative hosting, let’s consider the single Host model. Because only one person is associated with each listing, this data could easily be stored with a host_id column in our listings database. We can then perform a single check to figure out whether a user has permission to take an action on a listing. This might look like the following:

if (isListingHost) {
// Take action on listing
}

When Airbnb launched its first collaborative hosting product, Co-Hosting, we used these types of comparisons, just as we did with the single host model.

In our business logic, we need frequently to answer three types of questions around person-to-resource (e.g., listing, reservation, review) relationships:

  1. Permissions: Given a person and a resource, can this person take action X on this resource? The answer to this question helps us ensure that people only take actions on Airbnb that they are explicitly permitted to take. We must not permit someone to edit the price on an unrelated Host’s listing, for example.
  2. Collection Queries: Given a person, what are the resources that they can access? The answer to this question helps us determine which message threads to display in a person’s Airbnb inbox, for example.
  3. Hosts to Display and Notify: Given a resource, who should be displayed to guests, and who should be notified of updates to this resource? The answer to this question helps us determine who should be displayed as the Host(s) of this listing, for example.

After Co-Hosting, we soon found that performing the types of comparisons that we did for the single host model does not scale well to collaborative and more complex use cases.

  • Continually adding logic that is specific to a single type of collaborative hosting results in unwieldy code. For example, permissions checks might start to look like the following:
if (isListingHost || 
isListingCoHost ||
isListingTeamMember ||
isListingCollabHost1 ||
isListingCollabHost2 ||
...) {
// Take action on listing
}
  • Engineers who are building a new feature need to understand all of the existing types of collaborative hosting and decide how collaborative Hosts should interact with the feature (e.g., which types of Team members should have access to this feature?). If engineers do not include every use case, the feature will not be available to all Hosts.

Without any kind of unifying framework, product development for Hosts can quickly become a laborious process.

Today, because of our collaborative hosting infrastructure, product engineers do not need to worry about specific types of collaborative hosting. They only need to know three things, all of which we will cover in this post:

  1. For permissions, query Himeji.
  2. For collection queries, use the resource’s dedicated service.
  3. For Hosts to display or notify, use the Collaborative Hosting API.

Collaborative Hosting Core Architecture

We use user groups as the data model to represent any group of people. A user group is defined by an id, a group type (e.g., COHOSTING, TEAM), and a list of user group members.

Each member in a user group is defined by their Airbnb user id and a user group role, which allows us to differentiate between the different types of members within a user group. For example, if a Host (listing owner) has a Co-Host, then the corresponding user group would be a user group with type COHOSTING that has two members: the Host, who has the LISTING_OWNER role, and the Co-Host, who has the LISTING_COHOST role.

Diagram of how a Host and their Co-Host represented in the user group data model
A Host and their Co-Host represented in the user group data model

This model is extensible to hosting teams as well. We support several roles specific to Teams based on how hosting teams commonly break down responsibilities between team members, such as the LISTING_MANAGER role, the FINANCE_MANAGER role, and the GUEST_MANAGER role.

In the creation and deletion flows for a Co-Host or Team, the corresponding user group is updated accordingly.

Diagram showing that when Co-Hosts or Teams get updated in the product, in addition to the Co-Host and Teams sources of truth getting updated, the corresponding user groups get updated as well
Updates in product will trigger changes in both the source of truth (Co-Hosting or Teams) and the corresponding user groups

Resource <> User Group Associations

Now that we have a model for any collaborative hosting group, we want to associate each group with the group’s corresponding resources. This way, when we are trying to answer questions around whether a person has a relation with a given resource, there is a single source that will give us the answer, regardless of the specific collaborative relationship. We keep track of these resource <> user group associations by storing the Airbnb resource id, the user group id, and the timestamp when the association was created.

Example ListingUserGroupAssociations table showing that listing A has been associated with user group C and listing B has been associated with user group D
Example ListingUserGroupAssociations table showing that listing A has been associated with user group C and listing B has been associated with user group D

There are two scenarios in which resource <> user group associations need to be updated:

  1. When a collaborative hosting relationship gets updated. For example, when a hosting team gets created, all of the Team creator’s resources get associated with the Team’s corresponding user group
  2. When a collaborative hosting resource is updated. For example, when a guest books a reservation on a Co-Hosted listing, we need to associate the Co-Host user group with the new reservation so that the listing’s Co-Hosts can help the listing owner with hosting.

If updates in response to these events do not happen in a timely manner, the product experience might fall out of date. For example, if a Host adds a Co-Host to a listing, but the underlying association is not updated, the Co-Host will not have access to the listing and its reservations.

In a business of Airbnb’s size, keeping resource <> user group associations up to date can be challenging. The state of affairs is constantly changing, sometimes in quick succession; a Host might create a hosting team and then change their mind and immediately delete it. As a result, race conditions do occur.

For the rest of this section, we will cover Airbnb’s scalable system to keep resource <> user group associations up to date in spite of race conditions. In the subsequent section, we detail how Airbnb leverages these resource <> user group associations during product development.

A System for Achieving Accurate Resource <> User Group Associations

Diagram of the system that keeps resource <> user group associations updated
The system that keeps resource <> user group associations updated

When any resource changes, our system springs into action and fetches affected resources to perform association updates. Because there can be thousands of resources to fetch, we use an internal job queue and scheduling system to break down the work into jobs to avoid timeouts and process in parallel. For all affected resources, we compare their user group associations with the current state of Airbnb and update the associations if needed.

The side effect of processing updates in parallel is that there could be race conditions that result in inconsistencies between a source of truth and corresponding user group associations. For example, if a Host creates and then immediately deletes a Team, the resulting jobs would be executed in parallel, with the possibility of a downstream “create” job executing after a “delete” job.

To address any inconsistencies introduced, the system will next fetch the now-updated resource <> user group associations and compare them with the source of truth. If there are any mismatches, it fixes them using a resilient queuing system that guarantees eventual consistency.

There are two notable benefits to the design of this system:

  • Optimized Performance: Performing the anticipated updates first and then fixing inconsistencies retroactively allows for the vast majority of the processing to be done in batches and in parallel. This results in a much less expensive operation than if the resources were processed one-by-one right off the bat, even though the latter approach would eliminate the need for the step to fix inconsistencies.
  • Idempotent: Each resource update event triggers a re-calculation of associations that is agnostic to the specific type of update. As a result, we do not need to worry about receiving two opposite events, such as create and delete, in the wrong order. We thus have the guarantee that our system updates are idempotent.

Collaborative Hosting Infrastructure in Product Development

Now that we have a system for achieving accurate user group <> resource associations, let’s revisit the three types of questions around person-to-resource relationships that engineers need to answer during development.

1. Permissions

When checking if a user can edit the pricing on a listing, for example, we will now know whether the person is associated with this listing in any collaborative sense by checking the listing associations of the user’s user groups. We could find out, for example, that this user is a LISTING_MANAGER team member in a user group associated with this listing.

The last piece, then, is defining how roles map to actions — for example, we might decide that users who have the LISTING_COHOST or LISTING_MANAGER role can take the EDIT_PRICING action on listings with which their user group is associated. At Airbnb, this mapping happens in configs defined in Himeji, our central authorization framework described in this previous blog post. Given a user, a resource, and an action, Himeji computes whether that user is permitted to take the action on the resource.

Architecture diagram for Himeji where Himeji is pointing into data sources for resource user group associations, resources, and user groups
Architecture diagram for Himeji

2. Collection Queries

To fetch the resources that a person can access, we just need to make a single query by the person’s Airbnb user id and by the user group ids where the person has a permitted user group role. We use ElasticSearch to make resources searchable by user group id by joining the resource data source with the resource <> user group association table. This way, each resource’s ElasticSearch document has the list of user group ids that it is associated with.

Each resource’s designated data service then serves an endpoint (e.g., getListingsByFilters) that allows product engineers to pass a parameter (e.g., includeCollaborativeHosting=true) to indicate that resources should be fetched by both the person’s user id and user group ids.

Architecture diagram for collection queries showing mutations from resource user group associations and resources feeding into ElasticSearch, which gets queried, along with the user groups data source
Architecture diagram for collection queries

Note that, similar to above, we did not need to know anything about Co-Hosting or Teams specifically to answer these types of questions.

3. Determining Which Hosts to Display and Notify

The user(s) to display to guests or to notify about an update are not necessarily the same as the user(s) who have the corresponding permissions. For example, a Host who has a Co-Host may not want to receive notifications about guest messages, but they still want to access their Airbnb inbox.

As we saw previously, keeping track of the bespoke logic for each type of collaboration can become taxing for product teams. To address this issue, we built out a Collaborative Hosting API that takes all collaborative use cases into account, with endpoints such as getManagersToNotifyForReservation and getManagersToDisplay. Under the hood, we query the source of truth for each collaborative hosting use case and aggregate the results. This API abstracts away the specifics of collaborative hosting while still providing product engineers with the information that they need.

When naming API endpoints, we aimed to explicitly state the endpoint’s goal to reduce the chances that an engineer might misuse an API response. For example, the endpoint that returns users to notify for a reservation is named getManagersToNotifyForReservation, instead of getReservationManagers, which could be mistaken for a permissions endpoint that fetches the list of users that can modify a reservation.

Collaborative Hosting Playbook

With our clear structure around how collaborative hosting works across use cases, we can establish concise steps for new product development within the existing framework.

Introducing a New Type of Collaborative Hosting

When a new collaborative hosting use case is introduced, integrating it into Airbnb requires just a few key changes to get most of the way there:

  • Update/add your use case to the Himeji config for permissions
  • Update the resource <> user group association system to incorporate your use case
  • Update the collaborative hosting API endpoints to incorporate logic from your new use case when considering notifications or display

Introducing a New Airbnb Feature

When a new Airbnb feature is introduced, launching it to all Hosts just requires a few steps. Let’s say that Airbnb is building NewProduct. NewProduct will introduce a new type of resource, belos. We would need to:

  • Set up belo <> user group associations by adding belos to the user group <> resource association system
  • Use these belo <> user group associations to create a search index for belos so that we can fetch belos by user group ids
  • If needed, add a new endpoint for notifying and displaying users for belos

Conclusion

Airbnb has developed a collaborative hosting infrastructure that supports all types of Hosts. This makes it much easier to build products, as engineers just need to know about one central framework that will cover all hosting use cases. Collaborative hosting is critical to the success of many Hosts on Airbnb. A seamless developer experience when building for all Hosts allows us to empower Hosts to deliver great stays to guests.

If this type of work interests you, check out some of our related positions:

… and more at Careers at Airbnb!

Acknowledgments

Collaborative hosting is only possible as a result of the work of many incredible and mission-driven people over the years. Special thanks to Yi Lang Mok, Yan Li, Evelyn Shen, Amy Li, Aaron Holsonege, Eric Guan, Sujith Vishwajith, Alan Yao, JD Jiang, Brian Mason, Peggy Zheng, Chuan Shi, Dorothy Chang, Sharlene Luo, Jingyi Ni, Matias Figueroa, Charlie Jiang, Sushu Zhang, Ken Kao, Anna Majkowska, Jessica Tai, and many more.

All product names, logos, and brands are property of their respective owners. All company, product and service names used in this website are for identification purposes only. Use of these names, logos, and brands does not imply endorsement.

--

--