Why Privacy-First Social Features Are Hard

Building social features into a platform like Airbnb is a delicate balancing act. On one hand, guests and hosts want to connect—see who else is joining an Experience, message each other, build community. On the other hand, users expect absolute control over their personal data. A guest attending a "Pasta Making with Nonna" class might not want the same visibility as when they attend a "Goat Yoga" session with a different group.

Airbnb's engineering team tackled this by rethinking the fundamental identity model. The key insight: a user is not a profile. By separating the internal User entity from the public-facing Profile, they enabled flexible, context-aware visibility. This approach is a textbook example of privacy by design—and it's packed with lessons for any developer building multi-context social systems.

For a practical look at how similar architectural thinking applies to AI agent tooling, check out this guide on connecting AI agents to cloud prototyping environments.

Airbnb privacy-first architecture diagram showing User ID and Profile ID separation for context-aware social features Dev Environment Setup

The Core Architecture: User vs. Profile Separation

Airbnb introduced two distinct identifiers:

  • User ID – The internal, stable identifier for the actual person. Contains full PII (name, email, phone).
  • Profile ID – A public-facing identifier that represents how the user appears in a specific context. Each user can have many Profile IDs.

This decoupling enables:

  • Context-awareness: A Profile is only visible where it's relevant (e.g., a specific Experience).
  • Flexible representation: Users can choose different levels of detail for different contexts (first name only, full profile, etc.).
  • Privacy controls: By not linking Profile IDs across contexts, it becomes difficult to correlate a user's activities.

Real-World Example

Imagine Marie attends two Airbnb Experiences:

  1. "Pasta Making with Nonna" – She chooses to remain private. Profile A shows only her first name, no photo.
  2. "Goat Yoga" – She opts in to social features. Profile B shows her photo, guest stats, and "About me" info.

If Alex attends only "Goat Yoga," he sees Marie's full Profile B. But if Alex browses "Pasta Making with Nonna," he sees only "Marie"—no photo, no link between the two profiles. The system prevents cross-context correlation by design.

Code Example: Simplified Profile Creation Logic

# Pseudocode illustrating the User/Profile separation
from dataclasses import dataclass
from typing import Optional

@dataclass
class User:
    user_id: str
    full_name: str
    email: str
    phone: str

@dataclass
class Profile:
    profile_id: str
    user_id: str          # internal link, never exposed
    context_id: str       # e.g., experience_id or listing_id
    display_name: str
    photo_url: Optional[str] = None
    is_private: bool = False

def create_experience_profile(user: User, experience_id: str, is_private: bool) -> Profile:
    """
    Creates a context-specific profile for a user.
    Private profiles only show first name.
    """
    display_name = user.full_name.split()[0] if is_private else user.full_name
    return Profile(
        profile_id=generate_uuid(),
        user_id=user.user_id,
        context_id=experience_id,
        display_name=display_name,
        is_private=is_private
    )

Mobile app interface mockup of Airbnb Experiences social feature with privacy controls for guest profiles Developer Related Image

Permissions: Least-Privilege Access with Himeji

Airbnb uses Himeji, an in-house authorization system, to enforce access controls at the data layer. Himeji performs configurable relation denormalization at write time—when a profile or permission changes, it precomputes access rules. This makes read-time permission checks extremely fast and scalable.

Key design decisions:

  • Data-layer enforcement: Permissions are checked at the database query level, not just in the UI. This prevents accidental data leaks through API endpoints.
  • Least-privilege principle: Each interaction (guest-to-guest, guest-to-host, host-to-support) has its own permission boundary.
  • Profile ID as permission key: Access is granted based on the Profile ID, not the User ID. This ensures that even if a User ID is leaked, it cannot be used to access profiles from other contexts.

Migration Strategy: Automated Auditing + Human Review

Rolling out Profile IDs across Airbnb's codebase was a massive engineering effort. The team used a five-step approach:

  1. Automated auditing – Python scripts scanned the codebase for patterns associated with user data access.
  2. Team ownership mapping – Each finding was mapped to the owning team via directory structure.
  3. Manual review – Code owners manually verified each instance (internal vs. external use).
  4. AI-powered refactoring – AI tools suggested code changes, but engineers reviewed and refined every update.
  5. Company-wide collaboration – Engineering, product, privacy, legal, and more aligned on priorities.

Type safety was a critical safety net. Profile IDs and User IDs were given distinct types (e.g., ProfileId vs UserId in TypeScript) so the compiler caught mismatches. Automated tests and linters enforced boundaries.

For another example of how AI-assisted development can accelerate prototyping, see this article on building a Slack agent with Vercel's new skill.

Network diagram illustrating least-privilege access control and Himeji authorization system at Airbnb Development Concept Image

Limitations and Caveats

  • Complexity: The User/Profile separation adds indirection. Every new feature must consider which Profile ID to use, increasing development overhead.
  • User education: Guests need to understand why they have multiple profiles and how to control visibility. Poor UX can lead to confusion.
  • Cross-context inference: While the system prevents direct linking, determined attackers might still infer connections through metadata (e.g., booking times, shared payment methods).

Next Steps for Learning

  • Study privacy by design frameworks (GDPR, OWASP Top 10 for privacy).
  • Explore attribute-based access control (ABAC) as a more flexible alternative to RBAC.
  • Experiment with data-layer authorization tools like OPA (Open Policy Agent) or Himeji-like custom solutions.

Conclusion

Airbnb's approach to privacy-first social features is a masterclass in thoughtful architecture. By separating User and Profile IDs, they gave users granular control without sacrificing community. The combination of automated tooling, human review, and strong typing made the migration manageable at scale. For any developer building multi-context social systems, this pattern is worth studying—and adapting.

Source: Airbnb Engineering Blog

This content was drafted using AI tools based on reliable sources, and has been reviewed by our editorial team before publication. It is not intended to replace professional advice.