Katkat

Moderator System with Ranking, Communities, and Demotion

RedditSoftware Engineer · Technical Screen

Last updated

Design and implement an in-memory moderator management system supporting community-specific hierarchies, seniority-based permissions, and rank mutations.

Problem Statement

On community platforms like Reddit, moderators govern individual communities (subreddits). Moderator authority is hierarchical based on seniority: the earliest appointed moderators hold higher seniority (higher rank / lower numerical index) than later additions. A moderator can only perform administrative actions (such as demoting or removing another moderator) on someone who is strictly lower in rank than themselves.

Implement the ModeratorSystem class to support multi-community moderator management:

  • add_moderator(community_id: str, user_id: str) -> bool: Appoints user_id as the newest (lowest-ranked) moderator in community_id. If user_id is already a moderator in community_id, return False. Otherwise, append them to the hierarchy and return True.

  • demote_moderator(community_id: str, actor_id: str, target_id: str) -> bool: Moderator actor_id attempts to demote target_id by swapping target_id with the moderator immediately junior to them in rank. This operation succeeds only if:

    1. Both actor_id and target_id are moderators in community_id.
    2. actor_id strictly outranks target_id (i.e., actor_id has higher seniority than target_id).
    3. target_id is not already the lowest-ranked moderator. If all conditions are met, swap target_id with the moderator ranked directly below them and return True. Otherwise, make no changes and return False.
  • remove_moderator(community_id: str, actor_id: str, target_id: str) -> bool: Moderator actor_id removes target_id from community_id. This operation succeeds only if:

    1. Both actor_id and target_id are moderators in community_id.
    2. actor_id strictly outranks target_id. If conditions are met, remove target_id from the community's moderator list and return True. Otherwise, return False.
  • get_moderators(community_id: str) -> list[str]: Returns a list of all moderator user IDs in community_id in order from highest rank (most senior) to lowest rank. If the community does not exist or has no moderators, return an empty list [].


Example

system = ModeratorSystem()
system.add_moderator("programming", "alice")    # returns True; rank 0: alice
system.add_moderator("programming", "bob")      # returns True; rank 1: bob
system.add_moderator("programming", "charlie")  # returns True; rank 2: charlie

system.get_moderators("programming")
# returns ["alice", "bob", "charlie"]

system.demote_moderator("programming", "alice", "bob")
# returns True; alice (rank 0) outranks bob (rank 1).
# bob is swapped with charlie (rank 2).

system.get_moderators("programming")
# returns ["alice", "charlie", "bob"]

system.demote_moderator("programming", "alice", "bob")
# returns False; bob is already the lowest-ranked moderator.

system.remove_moderator("programming", "bob", "charlie")
# returns False; bob (rank 2) does not outrank charlie (rank 1).

system.remove_moderator("programming", "alice", "charlie")
# returns True; alice outranks charlie, charlie is removed.

system.get_moderators("programming")
# returns ["alice", "bob"]

Constraints

  • community_id, user_id, actor_id, and target_id are non-empty strings of alphanumeric characters.
  • The number of operations will not exceed 50,000.
  • The maximum number of moderators in any single community at any time will not exceed 1,000.
  • A user may moderate multiple distinct communities independently.

Hints

Hint 1

Consider tracking each community independently using a map from `community_id` to a community-specific data structure.

Hint 2

Because the number of moderators per community is at most 1,000, maintaining an ordered list alongside a hash map from `user_id` to index allows O(1) membership and rank checks with O(k) swaps or removals.

Hint 3

Pay special attention to self-action: an actor cannot strictly outrank themselves, so operations where `actor_id == target_id` must return False.

Follow-up questions

  • How would you design the data structure if a single community had 1,000,000 moderators and both rank checks and removals needed to run in O(log N) or O(1) time?
  • How would you support an audit log query `get_action_history(community_id)` that returns all historical promotions, demotions, and removals in chronological order?
  • In a distributed multi-threaded environment, how would you prevent race conditions when two senior moderators attempt to demote or remove overlapping sets of moderators concurrently?