← Atlassian Interview Insights

Atlassian·Software Engineer·Onsite - System Design / Architecture·Senior

SeniorPrefer not to say
May 2026

Summary

Atlassian system design round focused entirely on a tree/hierarchy storage service. Pretty deep dive into API design, schema choices, and edge cases. Felt like they really wanted to see how you reason through tradeoffs rather than just recite textbook answers.

Questions Asked (3)

Q1

Design a service that stores a hierarchical tree of nodes and exposes REST APIs. You need to support adding a node under a parent and retrieving all descendants of a given node recursively.

System DesignData ModelingTechnical Trade-offs
Author's notes

I jumped straight to adjacency list because it's the first thing that comes to mind, and the interviewer let me run with it for a bit before asking how I'd handle fetching all descendants efficiently.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying requirements and scale, then propose a data model that balances read and write efficiency for hierarchical data. Discuss trade-offs between adjacency list, materialized path, and closure table, and justify your choice based on the access patterns. Finally, outline the REST API design and how you would handle recursive retrieval efficiently.

Pro tip: Demonstrate awareness of real-world constraints by discussing how to handle deep hierarchies and large subtrees without blocking writes or causing performance bottlenecks. Mention pagination or asynchronous processing for very large descendant queries.

1. Clarify Requirements and Scale

Ask about expected read/write ratio, maximum depth, number of nodes, and latency requirements. This informs the choice of data model and API design.

2. Choose a Data Model

Evaluate options like adjacency list, materialized path, nested sets, and closure table. Discuss trade-offs in terms of query complexity, write cost, and storage overhead.

3. Design the REST API

Define endpoints for adding a node (POST /nodes with parentId) and retrieving descendants (GET /nodes/{id}/descendants). Consider response format, pagination, and error handling.

4. Implement Recursive Retrieval

Explain how to efficiently fetch all descendants using recursive CTEs (if using SQL) or iterative traversal. Discuss caching or denormalization to optimize frequent queries.

5. Address Scalability and Trade-offs

Discuss how the design scales with depth and breadth, and potential bottlenecks. Mention alternatives like storing the tree in a document store or using a graph database.

Key Points to Mention

  • Adjacency list is simple but recursive queries can be expensive; closure table or materialized path optimize reads at the cost of writes.
  • Use recursive CTEs (e.g., WITH RECURSIVE in PostgreSQL) for efficient descendant retrieval in relational databases.
  • Consider pagination or streaming for large descendant sets to avoid memory issues and timeouts.
  • Cache frequently accessed subtrees or use a read-optimized denormalized structure for hot paths.
  • Ensure API design follows REST best practices: proper HTTP methods, status codes, and resource naming.
  • Discuss consistency and concurrency: how to handle concurrent additions and deletions without corrupting the tree.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q2

Walk through your REST API design for this service. What endpoints would you expose, and what would the request and response shapes look like?

API & IntegrationsSystem Design
Author's notes

This part went okay.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the service's core resources and operations, then propose a resource-oriented REST API with standard HTTP methods and status codes. For each endpoint, describe the request/response shapes, including key fields, and justify design choices like pagination, filtering, and versioning.

Pro tip: Demonstrate awareness of Atlassian's API design guidelines by mentioning consistent error formats, hypermedia links, and idempotency for safe retries. Also, proactively discuss trade-offs between simplicity and flexibility (e.g., sparse fieldsets vs. over-fetching).

1. Identify Resources and Operations

List the main entities (e.g., users, projects, issues) and the CRUD operations needed. Group related operations under resource paths.

2. Define Endpoints and HTTP Methods

Map operations to RESTful endpoints using nouns and HTTP verbs (GET, POST, PUT, PATCH, DELETE). Include collection and item endpoints.

3. Specify Request and Response Shapes

For each endpoint, outline the JSON structure: required/optional fields, data types, and example payloads. Include headers like Content-Type and Authorization.

4. Address Cross-Cutting Concerns

Discuss pagination, filtering, sorting, versioning, error handling, and rate limiting. Explain how these are consistently applied across endpoints.

5. Summarize and Justify Design Choices

Recap the API design and explain why it meets the service's needs, mentioning trade-offs and alignment with REST best practices.

Key Points to Mention

  • Resource naming conventions (plural nouns, hierarchical relationships)
  • Proper use of HTTP status codes (200, 201, 400, 404, 500)
  • Pagination strategies (offset vs. cursor) and filtering/sorting parameters
  • Versioning approach (URI versioning, custom media types, or headers)
  • Error response format with consistent fields (code, message, details)
  • Idempotency and safe retries for POST/PUT operations

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q3

How would you prevent cycles from being introduced into the tree when adding new nodes?

System DesignTechnical Trade-offsAlgorithms & Data Structures
Author's notes

Short answer: validate at write time by checking if the target parent is already a descendant of the node being inserted.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the tree type (e.g., binary tree, B-tree, trie) and the insertion context, then discuss prevention strategies such as cycle detection during insertion, maintaining parent pointers, and using visited sets. Emphasize trade-offs between performance and safety, and mention how to handle concurrent modifications if applicable.

Pro tip: Mention that in production systems, you often combine structural invariants (like parent pointers) with runtime checks to catch cycles early, and that logging or alerting on cycle detection can help diagnose bugs in insertion logic.

1. Clarify the tree structure and insertion process

Ask questions to understand the tree type, whether nodes have parent pointers, and if insertions are single-threaded or concurrent. This ensures your answer is tailored to the specific scenario.

2. Identify potential cycle sources

Explain how cycles can occur, such as inserting a node that is already an ancestor of the target parent, or reusing a node that already has children. This shows you understand the problem deeply.

3. Propose prevention strategies

Discuss methods like checking if the new node is already in the tree (using a hash set), verifying parent-child relationships, or using a union-find data structure for dynamic connectivity. Mention that prevention is better than detection.

4. Discuss detection and recovery

If prevention is not possible, describe how to detect cycles during insertion (e.g., depth-first search from the new node to see if it reaches the parent) and how to handle them (e.g., reject insertion, log error).

5. Address trade-offs and scalability

Compare the overhead of prevention (e.g., extra memory for visited sets) versus detection (e.g., time for traversal). Mention how this scales with tree size and concurrency, and suggest appropriate data structures.

Key Points to Mention

  • Use of parent pointers to traverse upwards and check for cycles before insertion.
  • Maintaining a visited set or hash set of nodes during insertion to detect if the new node is already in the tree.
  • Union-Find (Disjoint Set Union) for efficient cycle detection in dynamic tree structures.
  • Trade-offs between prevention (e.g., O(1) checks with extra memory) and detection (e.g., O(n) traversal).
  • Handling concurrent insertions with locks or transactional memory to avoid race conditions that could introduce cycles.
  • Logging and monitoring for cycle detection events to identify bugs in insertion logic.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.