← Atlassian Interview Insights

Atlassian·Software Engineer·Technical Phone Screen·Senior

SeniorPrefer not to say
May 2026

Summary

Atlassian software engineer interview with a meaty trie-based URL router problem. The question had a lot of layers: core data structure, wildcard precedence, concurrency, complexity analysis, and tests all in one go. Felt like a system design and coding question smashed together.

Questions Asked (5)

Q1

Design and implement a URL routing matcher using a trie. It should support adding and removing route patterns at runtime, matching request paths, static segments, and a single-segment wildcard `*` that matches exactly one segment.

Algorithms & Data StructuresSystem Design
Author's notes

The trie structure itself wasn't the hard part.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying requirements and edge cases, then design a trie where each node represents a path segment and supports static children plus a wildcard child. Implement add, remove, and match operations with careful handling of wildcard backtracking and node cleanup, and analyze time/space complexity.

Pro tip: Explicitly discuss how to handle wildcard backtracking and node cleanup on removal to show you understand real-world trade-offs beyond basic trie operations.

1. Clarify Requirements and Edge Cases

Ask about path formats, wildcard semantics, overlapping routes, and removal behavior to ensure alignment before designing.

2. Design the Trie Structure

Define a node with a map for static children, a wildcard child pointer, and an optional handler/flag for terminal routes.

3. Implement Add and Remove Operations

For add, traverse or create nodes per segment; for remove, traverse, unmark terminal, and prune empty nodes bottom-up.

4. Implement Matching with Backtracking

Recursively match segments, trying static child first, then wildcard child, backtracking if needed to handle ambiguous patterns.

5. Analyze Complexity and Discuss Optimizations

State time complexity O(S) per operation (S = number of segments) and space O(total segments); mention potential optimizations like caching or priority rules.

Key Points to Mention

  • Trie node structure with static children map and wildcard child pointer
  • Wildcard matches exactly one segment, not zero or multiple
  • Backtracking during matching when both static and wildcard paths exist
  • Node cleanup and pruning on route removal to avoid memory leaks
  • Handling of overlapping routes and precedence (e.g., static over wildcard)
  • Time and space complexity analysis for add, remove, and match operations

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

Q2

How do you handle precedence when both a static segment and a wildcard could match the same path at the same position?

Algorithms & Data StructuresTechnical Trade-offs
Author's notes

Said static wins, wildcard is a fallback.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by defining the precedence rule clearly: static segments take priority over wildcards. Then explain how a router can implement this, such as by sorting routes by specificity or using a trie with backtracking. Finally, discuss trade-offs like performance and maintainability.

Pro tip: Mention that frameworks like Express and React Router use specificity-based ordering, and that documenting the precedence rule is crucial for API consistency. Also, consider edge cases like multiple wildcards and overlapping routes.

1. Define the precedence rule

State that static segments have higher priority than wildcards, and explain why: it provides predictable and intuitive routing.

2. Explain implementation strategies

Describe common approaches: sorting routes by specificity (e.g., number of static segments) or using a trie with backtracking to match the most specific route first.

3. Discuss trade-offs

Compare performance (sorting at startup vs. per-request backtracking) and maintainability (explicit ordering vs. implicit rules).

4. Handle edge cases

Address scenarios like multiple wildcards, overlapping routes, and how to resolve conflicts (e.g., longest static prefix wins).

5. Provide examples

Give a concrete example, such as '/users/me' vs. '/users/:id', and explain which matches and why.

Key Points to Mention

  • Static segments should always take precedence over wildcards to avoid ambiguity.
  • Specificity can be measured by the number of static segments or the position of wildcards.
  • Trie-based routers can efficiently match the most specific route by exploring static branches first.
  • Sorting routes by specificity at startup is a common and performant approach.
  • Documenting the precedence rule is essential for API consistency and developer experience.
  • Consider edge cases like multiple wildcards and overlapping routes to ensure robust routing.

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

Q3

What are the time and space complexities for insert, remove, and lookup in your trie implementation?

Algorithms & Data Structures
Author's notes

Answered this fine.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

First, clarify the trie's structure and assumptions (e.g., alphabet size, character set, and whether it's a standard trie or compressed). Then, for each operation (insert, remove, lookup), derive the time complexity in terms of the key length L and the number of children per node (alphabet size A), and the space complexity in terms of the total number of nodes N. Finally, summarize the complexities and note any trade-offs or optimizations.

Pro tip: Mention that while the theoretical time complexity is O(L) for all operations, the constant factor depends on the alphabet size and implementation details (e.g., array vs. hash map for children). Also, highlight that space can be a bottleneck and discuss possible optimizations like compressed tries or ternary search trees.

1. Clarify assumptions

State the trie's properties: alphabet size A, whether it's case-sensitive, and if it stores additional data per node. This sets the context for complexity analysis.

2. Analyze time complexity

For each operation, explain that it involves traversing or creating nodes along the key length L. Thus, time is O(L) for insert, remove, and lookup, assuming O(1) access to child nodes (e.g., via array or hash map).

3. Analyze space complexity

Space is proportional to the total number of nodes N, each storing up to A child pointers and possibly a value. So space is O(N * A) in the worst case, but often O(N) if using maps. Also consider the space for the keys themselves.

4. Discuss edge cases and optimizations

Mention that remove may require pruning unused nodes, which can affect time and space. Also note that compressed tries (radix trees) reduce space but may increase time for certain operations.

5. Summarize and compare

Conclude with a clear summary: time O(L) for all operations, space O(N * A) or O(N) depending on implementation. Compare with hash tables (O(1) average but O(L) for hashing) and balanced BSTs (O(L log A)).

Key Points to Mention

  • Time complexity for insert, remove, and lookup is O(L), where L is the length of the key.
  • Space complexity is O(N * A) in the worst case, where N is the number of nodes and A is the alphabet size, but can be O(N) with efficient child storage.
  • The constant factor for time depends on how children are stored (array, hash map, etc.).
  • Remove operation may involve pruning nodes, which can add overhead but doesn't change asymptotic complexity.
  • Compressed tries (radix trees) reduce space but may increase time for some operations.
  • Tries are efficient for prefix-based operations and have predictable performance independent of the number of keys.

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

Q4

How would you make this trie thread-safe when routes can be added or removed concurrently with reads?

System DesignTechnical Trade-offs
Author's notes

Talked through a read-write lock since reads heavily outnumber writes in a routing context.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the concurrency requirements and the trie's usage pattern (read-heavy vs write-heavy). Then propose a solution that balances simplicity and performance, such as using a read-write lock with fine-grained locking or a copy-on-write approach, and discuss trade-offs like latency, throughput, and memory overhead.

Pro tip: Mention that you would first measure the actual read/write ratio and contention before choosing a strategy, as premature optimization can lead to unnecessary complexity. Also, highlight that immutability and persistent data structures can simplify reasoning about thread safety.

1. Clarify requirements and constraints

Ask about the expected read/write ratio, latency requirements, and whether the trie is used for routing in a high-throughput system. This determines the appropriate concurrency strategy.

2. Identify atomic operations and invariants

Determine which operations must be atomic (e.g., adding/removing a route, traversing for a match) and what invariants must hold (e.g., no torn reads, no lost updates).

3. Evaluate concurrency control options

Consider coarse-grained locking (simple but low concurrency), fine-grained locking (complex but scalable), read-write locks (good for read-heavy), and lock-free/copy-on-write (high read performance but memory overhead).

4. Propose a solution with trade-offs

Select a strategy based on requirements, e.g., read-write lock for balanced workloads or copy-on-write for read-dominant. Explain how it ensures thread safety and its impact on performance and memory.

5. Discuss testing and validation

Mention how you would test the concurrent implementation, such as stress testing with concurrent readers and writers, and using tools like thread sanitizers to detect race conditions.

Key Points to Mention

  • Read-write locks allow multiple concurrent readers but exclusive writers, suitable for read-heavy routing tables.
  • Copy-on-write (or persistent data structures) provides lock-free reads by creating a new version on writes, but increases memory usage and write latency.
  • Fine-grained locking (e.g., per-node locks) can improve concurrency but risks deadlocks and complexity; need careful lock ordering.
  • Atomic references and compare-and-swap (CAS) operations can be used for lock-free updates, but require handling ABA problems and retries.
  • Trade-offs: simplicity vs performance, memory overhead vs latency, and consistency guarantees (e.g., linearizability vs eventual consistency).
  • Consider using existing concurrent data structures or libraries (e.g., Java's ConcurrentHashMap for a trie-like structure) to avoid reinventing the wheel.

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

Q5

Write unit tests covering edge cases: root path `/`, leading/trailing slashes, duplicate route registration, and overlapping wildcard patterns.

Algorithms & Data StructuresAPI & Integrations
Author's notes

Ran out of time here and only sketched two or three cases.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the router's expected behavior for each edge case, then design tests that isolate each scenario using a table-driven approach. Focus on both positive and negative cases, ensuring tests are readable and maintainable. Finally, discuss how to handle overlapping wildcards by testing precedence and specificity.

Pro tip: Mention that you'd use property-based testing for wildcard patterns to catch unexpected overlaps, and that you'd assert on the router's internal state (like registered routes) to verify duplicate handling.

1. Clarify Requirements and Edge Cases

Ask the interviewer about expected behavior for each edge case, such as whether duplicate routes should throw an error or override, and how wildcards should prioritize matches.

2. Set Up Test Structure

Use a table-driven test format to organize cases, with each test case specifying the route pattern, input path, and expected result. Include setup and teardown to reset the router state.

3. Write Tests for Each Edge Case

For root path, test that '/' matches only the root. For leading/trailing slashes, test normalization (e.g., '/foo/' vs '/foo'). For duplicates, test registration behavior. For overlapping wildcards, test that the most specific pattern wins.

4. Assert and Verify

Use assertions to check the matched handler, status codes, or thrown errors. For wildcards, verify that the correct handler is invoked and that parameters are extracted properly.

5. Review and Refactor

Ensure tests are independent, readable, and cover both success and failure paths. Consider adding comments for complex cases and refactoring repetitive setup into helper functions.

Key Points to Mention

  • Table-driven tests for clarity and scalability
  • Normalization of paths (leading/trailing slashes) and its impact on matching
  • Duplicate route registration: should it panic, error, or silently override?
  • Wildcard precedence: specificity order (e.g., static > param > wildcard)
  • Testing internal state (e.g., route tree) to verify registration
  • Using property-based testing for wildcard patterns to uncover edge cases

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