How Slack efficiently classifies emails at scale with an eventually consistent system



3085 views Backend System Design



One of the features of Slack is the ability to invite people to join a workspace by email. However, not all email addresses belong to the same organization, and it is a challenge to distinguish between internal and external invites.

In this article, we will discuss the technical details of how Slack classifies emails to provide a smoother product onboarding experience.

Need for classification

Onboarding employees and external vendors into a Slack workspace can be a tedious process. Depending on who is being invited, an internal or an external onboarding flow will be triggered. This can be as simple as showing a different dialogue.

A solution to this problem is an email classification service that classifies every email into an internal, or external category. This service kicks in when a user types in an email address during the invitation process.

Heuristics

Slack’s email classification service attempts to classify emails by using heuristics. For example,

  • if the user’s domain is one of the allowed ones, then the user is internal
  • if the domain of the inviter matches the domain of the invitee, the invitee is classified as per the inviter’s class.

But heuristics fail

The above two approaches are simple and effective for Slack workspaces that are homogeneous (having one or few email domains). But, things become interesting when the number of email domains is many and there is no one rule that will fit.

Slack solves this classification problem by keeping track of all domains part of a workspace and using that aggregated count to determine the class.

Implementation Details

To implement this classification, Slack maintains a table called domains which stores the aggregation (count) per (team, domain, role). This table effectively answers how many users of a workspace have a particular domain and a specific role.

For example workspace, A has 68 members having the role member, while 6 members with the role admin.

The count is maintained with eventual consistency. User-created, updated, and deleted events are sent to Kafka, and consumed by a set of consumers to update the domains table.

Classifying Threshold

Slack operates with a threshold of 10%, which implies that a domain is considered internal if there are at least 10% or more employees in the organization with a given domain, otherwise, it is classified as external.

Adding a new user

While processing the user_created event, Slack does upsert instead of an update as upserts allow us to not check for the existence of the row with matching constraints.

UPSERT count = count + 1 WHERE
team_id = 1 AND domain = "bar.com" AND role = "member";

Changing the role

If a user’s role changes from member to admin, the count for the member role is decremented, and the count for the admin role is incremented transactional.

UPSERT count = count + 1 WHERE
team_id = 1 AND domain = "bar.com" AND role = "admin";

UPSERT count = count - 1 WHERE
team_id = 1 AND domain = "bar.com" AND role = "member";

Reprocessing the message

One challenge is that user events can be processed twice causing the numbers to drift. To overcome this challenge, Slack uses a healing mechanism that automatically corrects drifts.

The healer process goes through all the users, until a certain timestamp, and extracts their email domains to perform the count in memory. It then computes the drift from numbers stored in the domains table.

Instead of updating the database with the observed count, it pushes the drift as a separate message +N / -N. This ensures that numbers in the domain table always converge to the correct value and are eventually consistent.

Conclusion

Slack’s email classification service is a critical feature that helps give a smoother invitation experience to users. Classifying emails accurately is a challenging problem, but Slack has implemented an effective solution by using a table to maintain counts and eventual consistency.


Arpit Bhayani

Arpit's Newsletter

CS newsletter for the curious engineers

❤️ by 38000+ readers

If you like what you read subscribe you can always subscribe to my newsletter and get the post delivered straight to your inbox. I write essays on various engineering topics and share it through my weekly newsletter.




Other essays that you might like


Thundering Herd Problem and How not to do API retries

6281 views 270 likes 2023-01-31

System Design for Experienced Engineers: https://arpitbhayani.me/masterclass Become a member for exclusive in-depth vide...

Designing Idempotent API Endpoints for Payments at Stripe

6253 views 326 likes 2023-01-29

System Design for Experienced Engineers: https://arpitbhayani.me/masterclass Become a member for exclusive in-depth vide...

How Slack efficiently classifies emails at scale with an eventually consistent system

3085 views 103 likes 2023-01-13

System Design for Experienced Engineers: https://arpitbhayani.me/masterclass Become a member for exclusive in-depth vide...

How @ShopifyEngineering avoids hot shards by moving data across databases without any downtime

4617 views 170 likes 2023-01-08

System Design for Experienced Engineers: https://arpitbhayani.me/masterclass Become a member for exclusive in-depth vide...


Be a better engineer

A set of courses designed to make you a better engineer and excel at your career; no-fluff, pure engineering.


Paid Courses

System Design for Beginners

A masterclass that helps early engineers and product managers become great at designing scalable systems.

180+ learners

Details →

System Design Masterclass

A masterclass that helps you become great at designing scalable, fault-tolerant, and highly available systems.

1000+ learners

Details →

Redis Internals

Learn internals of Redis by re-implementing some of the core features in Golang.

98+ learners

Details →

Free Courses

Designing Microservices

A free playlist to help you understand Microservices and their high-level patterns in depth.

823+ learners

Details →

GitHub Outage Dissections

A free playlist to help you learn core engineering from outages that happened at GitHub.

651+ learners

Details →

Hash Table Internals

A free playlist to help you understand the internal workings and construction of Hash Tables.

1027+ learners

Details →

BitTorrent Internals

A free playlist to help you understand the algorithms and strategies that power P2P networks and BitTorrent.

692+ learners

Details →