Atlassian Traffic Architecture (Blind SWE Case Study)
A strong traffic-architecture answer starts with a clear product scope, explicit load assumptions, and a request path you can explain from client to storage. Then show how routing, data, caching, and background work handle normal traffic and failures. Treat every scale figure as an assumption, compare at least one alternative, and never present a practice design as Atlassian’s actual system.
A common myth is that system-design interviews reward the biggest diagram or the most impressive technology list. They do not. A design is easier to assess when you explain what the product must do, what you assume about its traffic, and why each part is there.
This guide uses an Atlassian-like collaboration product as a practice scenario. It is not a description of Atlassian’s internal systems, an official interview rubric, or a claim about questions you will receive. I use explicit assumptions so you can change them when an interviewer adds new requirements.
Frame the case before drawing the architecture
A traffic-architecture case asks how requests enter a service, reach the right data and workers, and remain safe under load or failure. For a collaboration product, users might read a project board, update an issue, search work, and receive notifications. Define these actions before choosing components.
Start by confirming scope. Ask whether the design covers one product feature or the full platform, whether users need near-real-time updates, and whether the system must serve multiple regions. If the interviewer does not specify, state reasonable assumptions and invite correction.
A useful opening could be: “I’ll design issue reads and updates for a multi-tenant work-tracking service. I’ll include authentication, persistence, and notifications, but leave full-text search internals as a separate service.”
“Tenant” means a customer organization whose data must remain separate from other organizations. “Availability” means the share of time a service can respond as expected. Neither term tells you what the product’s exact target is; ask or label your assumed target.
I would write the assumptions where the interviewer can see them:
- Main actions: read an issue, create or update an issue, and trigger a notification.
- Traffic: reads outnumber writes, but the ratio needs confirmation.
- Freshness: an update should appear quickly, while search indexing may lag.
- Data: issue history must persist; notification delivery can be retried.
- Isolation: each request must be checked against the user’s tenant and permissions.
Keep the initial scope small. Add search, analytics, attachments, or global active-active writes only when the requirements call for them. Takeaway: make the problem concrete before you make the design large.
Estimate traffic with visible assumptions
Capacity estimation is a rough model of demand, not a guess presented as fact. Estimate peak requests per second, read and write share, request size, and data growth. Show the arithmetic so the interviewer can replace any assumption and see how the design changes.
Suppose, only for practice, you assume 1 million daily active users, each making 100 API requests per day. That gives 100 million requests daily. Dividing by 86,400 seconds gives about 1,160 requests per second on average. If you assume a peak ten times the average, the design point is about 11,600 requests per second. These are invented scenario inputs, not Atlassian traffic figures.
Then split the load. If 80% are reads, peak reads are roughly 9,280 per second and writes about 2,320. Ask whether those requests include static assets, polling, retries, or background jobs. A changed assumption can shift the bottleneck from the database to the network or worker queue.
| Input | Practice assumption | Why it matters |
|---|---|---|
| Daily users | 1 million | Starting point for request volume |
| Requests per user per day | 100 | Must be checked against user behavior |
| Peak multiplier | 10× average | Tests burst handling |
| Read share | 80% | Shapes caching and database capacity |
| Average API payload | 2 KB | Helps estimate network and memory use |
For storage, separate current data from growth. For example, if the scenario creates 2 million records per day at 1 KB each, raw new record data is about 2 GB per day before indexes, replicas, and history. Say those additions are not included. Avoid false precision: record sizes, indexes, and retention can change the result.
Treat a peak multiplier as an assumption, not a universal threshold. If the interviewer changes it, recalculate. Takeaway: use estimates to find pressure points, not to claim knowledge of real company scale.
Sketch the request path and service boundaries
A request path shows how a call travels through the system. A service boundary marks a part that can be built, scaled, or operated separately. Draw only the parts needed for the stated product behavior, then explain what each one owns.
A basic path could be:
Client → edge routing → load balancer → API service → issue service → database
The API service handles authentication, request checks, and routing. The issue service applies product rules, such as whether a user can edit an issue. A database stores durable issue data. A cache may serve safe, frequently read data, and a queue can hand off work that need not finish before the user receives a response.
Do not split every function into a microservice by default. One service may be simpler to operate when the team or product scope is small. Separate services can help teams scale or deploy parts independently, but they add network calls, failure points, and operational work.
| Option | Useful when | Main cost or risk |
|---|---|---|
| One application service | Scope is modest and shared changes are common | Scaling parts separately is harder |
| Separate issue and notification services | Workloads or ownership differ | More calls, monitoring, and failure handling |
| Synchronous notification call | User must know delivery succeeded now | Slow or failed delivery can delay the update |
| Queue-based notification | Delivery can happen after the update | Requires retry, duplicate, and backlog controls |
In a practice discussion, I might draw the simplest path first, then add a queue when the requirement says a notification should not block an issue update. That is a hypothetical design choice, not a report of a real Atlassian system. Takeaway: each component should answer a requirement or reduce a stated risk.
Explain data, caching, and tenant isolation
Persistence means storing data so it survives a service restart. A cache keeps a temporary copy to reduce repeated work. For a work-tracking product, durable issue records and activity history may need different access patterns, so state what you store and how users read it.
A relational database is a reasonable starting point when updates must preserve clear relationships and transactions. A key-value or document store may fit access patterns that need flexible records or predictable lookups. Do not claim one is always better. Explain the query pattern and the consistency needs, then compare the trade-off.
A cache can help with repeated reads, such as project settings, but it can serve stale data. Define a simple policy: expire entries after a short period, or invalidate them when the underlying record changes. If correctness matters more than speed for a particular action, read the durable source instead.
Tenant isolation should be part of the data path, not a final note. Check the user’s identity and permission, then scope every read and write to the tenant. A tenant ID in a database key or query can support this, but it does not replace access checks. Consider noisy tenants, too: one customer’s burst should not consume all shared capacity.
For writes, describe how you avoid duplicate effects. A client may retry after a timeout even if the first request succeeded. An idempotency key is a unique request token that lets the service recognize a repeated operation and avoid applying it twice. Takeaway: explain the data model, freshness, access rules, and retry behavior together.
Design for failure and safe operation
Reliability is the ability to keep useful service behavior during faults and recover when parts fail. A complete design names likely failures, limits their effect, and shows how the team would detect and respond to them. Avoid promising that every component will never fail.
Use bounded timeouts so a request does not wait forever. Retry only when a failure may be temporary, and use a limit with increasing delays to avoid making an outage worse. For write requests, pair retries with idempotency. If a service cannot keep up, backpressure means slowing or rejecting new work rather than allowing an endless queue to form.
| Failure | Possible response | Signal to watch |
|---|---|---|
| Database slows down | Timeouts, limited retries, protect critical writes | Query latency and error rate |
| Queue grows | Add worker capacity or reduce optional work | Queue depth and oldest message age |
| One tenant floods requests | Per-tenant rate limit and fair capacity | Requests and throttles by tenant |
| Cache becomes unavailable | Fall back carefully to the database | Cache errors and database load |
| Deployment introduces errors | Stop rollout or roll back | Error rate and latency by version |
A rate limit caps how quickly a user or tenant can make requests. It can protect shared services, but should return a clear response and avoid blocking normal work without reason. Monitor latency, error rate, saturation, queue depth, and request volume. Set alert thresholds from service objectives and observed baselines; there is no verified universal number for this case.
For recovery, state what data can be restored and how you would test that process. If the design uses multiple regions, clarify whether reads, writes, or both can move between them and what happens to conflicting updates. Takeaway: pair each protection with a failure mode and a measurable signal.
Validate the design under changing constraints
Validation means testing whether the design still meets its goals when traffic, dependencies, or product needs change. In an interview, walk through a few stress cases rather than adding components without a reason. This shows where your assumptions matter.
Try these changes:
- Traffic doubles: identify whether the bottleneck is API capacity, database reads, or queue workers. Scale the constrained part and recheck shared dependencies.
- A traffic spike hits one tenant: apply fair-use limits and protect capacity for other tenants.
- The database becomes slow: reduce optional work, limit retries, and preserve the most important user actions.
- A region is unavailable: explain which requests continue, what data may be stale, and how service is restored.
- Search indexing falls behind: keep issue writes available if the product allows it, and show indexing delay as a separate health signal.
I recommend drawing the normal request path and one failure path. Then narrate the trade-off: “This queue protects the user-facing update from notification delays, but it means delivery is eventually consistent.” That phrase means the notification may arrive later, while the issue update is already saved.
Reserve time to revisit assumptions. A design for read-heavy traffic may change if the interviewer says writes must be globally consistent. A single-region design may be suitable for a narrow scope, but a strict recovery target could require a more complex multi-region plan. Takeaway: show how the design changes when constraints change, rather than defending the first diagram.
Rehearse the case and connect it to SWE work
A strong practice answer is structured and adaptable. It does not depend on memorizing a diagram. I use a timed sequence: clarify the task, estimate demand, draw the path, explain storage and reliability, then test failure cases and summarize trade-offs.
For a 40-minute practice session, one possible schedule is 5 minutes for requirements, 5 for estimates, 15 for the core design, 10 for failure cases, and 5 for review. This is a rehearsal plan, not an Atlassian interview format. Ask a peer to change one requirement midway and note whether you update the design or keep defending an old assumption.
Use a short checklist after each mock:
- Did I state what was in and out of scope?
- Were load numbers labeled as assumptions and calculated clearly?
- Could I explain each component’s purpose?
- Did I cover retries, tenant isolation, and overload?
- Did I compare a real alternative and its cost?
- Did I identify metrics that would reveal a problem?
These skills are relevant to backend, platform, infrastructure, and distributed-systems engineering work. They demonstrate how you reason about service boundaries, data, reliability, and operations. They do not guarantee an interview result or job outcome. Confirm the interview format with the recruiter or official materials, since company-specific expectations can differ by role.
Conclusion: prepare to reason in public. Start with the product behavior, make estimates easy to challenge, and tie each architecture choice to a requirement. Label the design as a practice scenario, not an account of Atlassian’s production architecture. That combination is more useful than memorizing a “correct” answer.
FAQ: traffic architecture interview preparation
These answers recap the main decisions in a traffic-design case. They distinguish general preparation guidance from company-specific claims, and they keep the focus on a practical collaboration-product scenario.
Is this the architecture Atlassian uses in production?
No. It is a practice design for an Atlassian-like product. Do not treat it as a verified description of Atlassian’s internal systems.
Is this an official Atlassian interview question or rubric?
No. The scenario and preparation targets here are not verified hiring materials. Confirm interview expectations with the recruiter or official sources.
What should I clarify first?
Ask which user actions are in scope, what performance and availability needs apply, how fresh data must be, and how tenant data is isolated.
How should I estimate requests per second?
State user and request assumptions, calculate daily volume divided by seconds per day, then apply a clearly labeled peak factor. Recalculate if assumptions change.
Should I use microservices?
Only when separate scaling, ownership, or workload needs justify the added network and operational complexity. A simpler service boundary may be enough.
When should I add a queue?
Use one when work can finish after the user’s request, such as sending a notification. Explain retries, duplicate handling, and how you will monitor backlog.
How do I address a noisy tenant?
Use per-tenant limits and monitor tenant-level usage. Explain how you protect shared capacity without blocking normal customer activity.
Which metrics should I mention?
Cover request volume, latency, error rate, resource saturation, queue depth, and tenant-level throttling. Set thresholds from stated goals and observed baselines, not unsupported universal values.
What if the interviewer changes the traffic assumptions?
Update the arithmetic and identify the new bottleneck. Then explain which component or trade-off changes and why.
How should I avoid overstating company-specific knowledge?
Label figures as assumptions, present the design as a hypothetical case, and avoid claims about Atlassian’s systems or hiring rules unless an authoritative source supports them.
(This article was written by one of our staff writers, James Holloway. Visit our Meet the Team page.)
