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.

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:
- "Pasta Making with Nonna" – She chooses to remain private. Profile A shows only her first name, no photo.
- "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
)

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:
- Automated auditing – Python scripts scanned the codebase for patterns associated with user data access.
- Team ownership mapping – Each finding was mapped to the owning team via directory structure.
- Manual review – Code owners manually verified each instance (internal vs. external use).
- AI-powered refactoring – AI tools suggested code changes, but engineers reviewed and refined every update.
- 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.

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