A Software Engineer at Mirage is responsible for building the core technologies that power our platform. Whether you are working on Backend, Web Product, or Applied AI, you will design systems that process massive amounts of data, render seamless user interfaces, and deploy intelligent models to production. Our engineering team tackles complex challenges in real-time collaboration, high-throughput data processing, and state-of-the-art AI integration. The engineering culture at Mirage values speed, pragmatic decision-making, and high technical standards. Engineers do not just write code; they own product features from ideation to deployment, directly impacting how customers interact with our platform. You will work in a fast-paced environment where your contributions directly influence the product roadmap and user experience. This role is critical to the scale and success of Mirage. As we continue to expand our product offerings and user base, our software engineers ensure that our infrastructure remains highly performant, reliable, and secure. It is an exciting opportunity to work on cutting-edge technologies alongside a highly collaborative and ambitious team.
Recruiter Call
reportedInitial conversation with a recruiter to align on background, career interests, and compensation expectations.
What to demonstrate
- Initial conversation with a recruiter to align on background, career interests, and compensation expectations
- Depth in Backend Software Engineering
How to prepare
- Be able to walk your CV end to end in two minutes, and say why this company specifically.
- Have your salary expectations, notice period and location constraints ready, and ask for the rest of the loop in writing.
Technical Screen
reportedHands-on coding session or system design discussion based on level and specialization.
What to demonstrate
- Hands-on coding session or system design discussion based on level and specialization
- Depth in Backend Software Engineering
How to prepare
- Answer aloud and timed: Given an array of integers, find the contiguous subarray with the largest sum.
- Answer aloud and timed: Implement a trie data structure to support autocomplete functionality.
Onsite Interview
reportedMultiple deep-dive sessions focusing on coding, system architecture, and behavioral alignment.
What to demonstrate
- Multiple deep-dive sessions focusing on coding, system architecture, and behavioral alignment
- Depth in Backend Software Engineering
How to prepare
- Answer aloud and timed: Write a function to detect cycles in a large directed graph representing microservice dependencies.
- Answer aloud and timed: Design a real-time collaborative document editing system.
PracHub editorial advice for the preparation topics above.
Going into the loop without having done this.
Think out loud: During coding and system design rounds, communicate your thought process constantly. Interviewers care as much about how you arrive at a solution as they do about the solution itself.
Going into the loop without having done this.
Clarify requirements early: Never jump straight into writing code or drawing architecture diagrams. Spend the first few minutes asking clarifying questions to define the scope and constraints of the problem.
Going into the loop without having done this.
Make sure to test your code with edge cases during the coding round before declaring that you are finished. This shows strong attention to detail and production-level discipline.
Going into the loop without having done this.
Focus on trade-offs: There is rarely a single "correct" answer in system design. Always present multiple options and explain why you chose one over the other, highlighting trade-offs in latency, cost, and complexity.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
Given an array of integers, find the contiguous subarray with the largest sum.
Given an array of integers, find the contiguous subarray with the largest sum.
Approach
- Restate the input: its shape, its size, and what is guaranteed about it.
- Name the brute-force solution and its complexity before improving on it.
- Choose the data structure from the access pattern, not from familiarity.
- State the target complexity and say which constraint rules the naive version out.
Follow-up
- How does this change if the input no longer fits in memory?
- What is the worst case, and how likely is it on real data?
Implement a trie data structure to support autocomplete functionality.
Implement a trie data structure to support autocomplete functionality.
Approach
- Restate the input: its shape, its size, and what is guaranteed about it.
- Name the brute-force solution and its complexity before improving on it.
- Choose the data structure from the access pattern, not from familiarity.
- State the target complexity and say which constraint rules the naive version out.
Follow-up
- How does this change if the input no longer fits in memory?
- What is the worst case, and how likely is it on real data?
Build a performant, reusable autocomplete search component using vanilla JavaScript or React.
Build a performant, reusable autocomplete search component using vanilla JavaScript or React.
Approach
- Restate the input: its shape, its size, and what is guaranteed about it.
- Name the brute-force solution and its complexity before improving on it.
- Choose the data structure from the access pattern, not from familiarity.
- State the target complexity and say which constraint rules the naive version out.
Follow-up
- How does this change if the input no longer fits in memory?
- What is the worst case, and how likely is it on real data?
Replace offset paging on the resource feed with keyset
resource holds resource_id, tenant_id, owner_user_id, title, body_ref, version, status ('draft','active','archived','deleted'), created_at, updated_at, deleted_at, with an index on (tenant_id, status, updated_at DESC, resource_id DESC). The listing endpoint returns active resources for one tenant, newest update first, 50 per page, today with LIMIT 50 OFFSET n. Tenants reach page 400 and rows are created while they read. Write the keyset query, define what the cursor carries and how it is encoded, and say which part of the index each predicate uses. Assume PostgreSQL 16.
Approach
- Name the two failures separately. OFFSET 20000 makes the server produce and discard 20,000 rows, so page cost grows with depth rather than with page size. Independently, any write that changes how many rows sort above the offset moves the window between two fetches, and the direction decides which anomaly you get: an insert lands at the head of updated_at DESC and pushes already-returned rows down past the boundary, so they are returned a second time; a delete above the offset, or a row whose updated_at is bumped above the cursor, pulls rows up and one is never returned at all. Nothing in the response reveals either.
- Write the seek: WHERE tenant_id = $1 AND status = 'active' AND (updated_at, resource_id) < ($2, $3) ORDER BY updated_at DESC, resource_id DESC LIMIT 50. The row-value comparison is one index range rather than a disjunction, and both columns are NOT NULL, which is what makes that comparison well defined.
- Map each predicate onto the index: tenant_id and status are equality on the leading columns, (updated_at, resource_id) is the range, and the ORDER BY matches the index order so no Sort node appears and the scan stops after 50 rows. The DESC in the definition only matters for mixed directions — a plain ascending btree on the same columns is read backwards for this query.
- Put both sort columns in the cursor and nothing the client can tamper with into another tenant: base64 of (updated_at, resource_id), validated server-side, with tenant_id taken from the principal.
Follow-up
- The client asks for 'jump to page 400'. What do you offer instead, and what does the honest version cost?
- Sort order becomes user-selectable across four columns. How many indexes is that, and which would you refuse to add?
Write the update path that detects a concurrent edit
resource carries version INT NOT NULL DEFAULT 1. resource_revision holds revision_id, resource_id, version, actor_user_id, change_kind, patch JSONB, request_id, created_at with UNIQUE (resource_id, version). outbox_event holds aggregate_type, aggregate_id, aggregate_version, event_type, payload, status. A PUT carries the version the client read. Write the exact statements for the single transaction that applies the edit, records the revision and enqueues 'resource.updated', and give the handler's branch on zero affected rows. Then say what PostgreSQL 16 does under READ COMMITTED when two of these updates hit one row at once.
Approach
- One transaction, three writes, no network call inside it: UPDATE resource SET title = $3, version = version + 1, updated_at = now() WHERE resource_id = $1 AND tenant_id = $4 AND version = $2; then INSERT the resource_revision row at version $2 + 1; then INSERT the outbox_event row at the same aggregate_version. The event goes to a table rather than a broker because no transaction spans both.
- Branch on the affected-row count before doing anything else. Zero has three causes — stale version, wrong tenant, row gone — so re-read once and map to 409 carrying the current version, or 404 for an id outside the caller's tenant, which also stops the endpoint confirming that another tenant's id exists.
- State the engine behaviour instead of assuming it. Under READ COMMITTED the second UPDATE blocks on the row lock, and when the first commits PostgreSQL re-evaluates the WHERE clause against the newly committed row, so the version predicate now fails and the statement reports zero rows. Under REPEATABLE READ the identical collision raises SQLSTATE 40001 instead, so the handler must fold both shapes into one conflict response.
- Keep UNIQUE (resource_id, version) even though the predicate already serialises writers. It is what makes a lost update unwritable if any other path ever reaches the revision table, and it converts a logic bug into 23505 rather than into a silently missing history row.
Follow-up
- A client sends the version it read ten minutes ago and the resource has moved three versions. What is in your 409 so it can resolve the conflict without a full re-fetch?
- Two editors, two disjoint fields, no overlap. Does your answer still refuse the second write, and should it?
Implement a rate limiter to throttle API requests based on user IP.
Implement a rate limiter to throttle API requests based on user IP.
Approach
- Say who the caller is and what they do when the call fails halfway.
- Define the identity of a request so a retry cannot double-apply it.
- Separate accepted, pending, failed and confirmed; they are different facts.
- Design the error taxonomy before the success shape; callers branch on it.
Follow-up
- What happens if the caller retries after a timeout?
- How does a client discover it is on an old version of this contract?
Design an efficient in-memory cache with eviction policies like LRU or LFU.
Design an efficient in-memory cache with eviction policies like LRU or LFU.
Approach
- Fix the scope first: who calls this, how often, and what they do when it fails.
- Name the read and write paths separately; they rarely have the same bottleneck.
- Choose a partition key and say what query it makes expensive.
- State the consistency you need, and where you are willing to be stale.
Follow-up
- What breaks first when traffic grows ten times?
- How does this behave when that dependency is down for an hour?
Write a function to detect cycles in a large directed graph representing microservice dependencies.
Write a function to detect cycles in a large directed graph representing microservice dependencies.
Approach
- Fix the scope first: who calls this, how often, and what they do when it fails.
- Name the read and write paths separately; they rarely have the same bottleneck.
- Choose a partition key and say what query it makes expensive.
- State the consistency you need, and where you are willing to be stale.
Follow-up
- What breaks first when traffic grows ten times?
- How does this behave when that dependency is down for an hour?
Design a real-time collaborative document editing system.
Design a real-time collaborative document editing system.
Approach
- Fix the scope first: who calls this, how often, and what they do when it fails.
- Name the read and write paths separately; they rarely have the same bottleneck.
- Choose a partition key and say what query it makes expensive.
- State the consistency you need, and where you are willing to be stale.
Follow-up
- What breaks first when traffic grows ten times?
- How does this behave when that dependency is down for an hour?
How would you design a scalable notification system that supports SMS, email, and push notifications?
How would you design a scalable notification system that supports SMS, email, and push notifications?
Approach
- Fix the scope first: who calls this, how often, and what they do when it fails.
- Name the read and write paths separately; they rarely have the same bottleneck.
- Choose a partition key and say what query it makes expensive.
- State the consistency you need, and where you are willing to be stale.
Follow-up
- What breaks first when traffic grows ten times?
- How does this behave when that dependency is down for an hour?
Design a high-throughput backend system to ingest and process metrics from millions of devices.
Design a high-throughput backend system to ingest and process metrics from millions of devices.
Approach
- Fix the scope first: who calls this, how often, and what they do when it fails.
- Name the read and write paths separately; they rarely have the same bottleneck.
- Choose a partition key and say what query it makes expensive.
- State the consistency you need, and where you are willing to be stale.
Follow-up
- What breaks first when traffic grows ten times?
- How does this behave when that dependency is down for an hour?
Explain how you would architect a content delivery network (CDN) to serve static and dynamic assets globally.
Explain how you would architect a content delivery network (CDN) to serve static and dynamic assets globally.
Approach
- Fix the scope first: who calls this, how often, and what they do when it fails.
- Name the read and write paths separately; they rarely have the same bottleneck.
- Choose a partition key and say what query it makes expensive.
- State the consistency you need, and where you are willing to be stale.
Follow-up
- What breaks first when traffic grows ten times?
- How does this behave when that dependency is down for an hour?
Design a distributed rate limiter that can handle millions of requests per second across multiple data centers
Design a distributed rate limiter that can handle millions of requests per second across multiple data centers.
Approach
- Fix the scope first: who calls this, how often, and what they do when it fails.
- Name the read and write paths separately; they rarely have the same bottleneck.
- Choose a partition key and say what query it makes expensive.
- State the consistency you need, and where you are willing to be stale.
Follow-up
- What breaks first when traffic grows ten times?
- How does this behave when that dependency is down for an hour?
How do you optimize web application performance, specifically focusing on initial load time and rendering bott
How do you optimize web application performance, specifically focusing on initial load time and rendering bottlenecks?
Approach
- Clarify what is being asked and what a complete answer contains.
- State your assumptions explicitly before working the problem.
- Say what you would check first and why it is the highest-information step.
- Work from the requirement backwards to the design.
Follow-up
- What assumption would you test first?
- How would you know your answer was wrong?
Describe how you would manage state in a highly interactive, complex single-page application.
Describe how you would manage state in a highly interactive, complex single-page application.
Approach
- Clarify what is being asked and what a complete answer contains.
- State your assumptions explicitly before working the problem.
- Say what you would check first and why it is the highest-information step.
- Work from the requirement backwards to the design.
Follow-up
- What assumption would you test first?
- How would you know your answer was wrong?
Explain the security implications of Cross-Site Scripting (XSS) and Cross-Site Request Forgery (CSRF), and how
Explain the security implications of Cross-Site Scripting (XSS) and Cross-Site Request Forgery (CSRF), and how to mitigate them.
Approach
- Clarify what is being asked and what a complete answer contains.
- State your assumptions explicitly before working the problem.
- Say what you would check first and why it is the highest-information step.
- Work from the requirement backwards to the design.
Follow-up
- What assumption would you test first?
- How would you know your answer was wrong?
Design a virtualized list component that can render millions of items smoothly without lagging the browser UI.
Design a virtualized list component that can render millions of items smoothly without lagging the browser UI.
Approach
- Fix the scope first: who calls this, how often, and what they do when it fails.
- Name the read and write paths separately; they rarely have the same bottleneck.
- Choose a partition key and say what query it makes expensive.
- State the consistency you need, and where you are willing to be stale.
Follow-up
- What breaks first when traffic grows ten times?
- How does this behave when that dependency is down for an hour?
Describe a situation where you had to debug a critical production issue under pressure.
Describe a situation where you had to debug a critical production issue under pressure.
Approach
- Establish what changed and when, before forming any theory.
- Pick a bisection that eliminates candidates whichever way it turns out.
- Check the instrumentation before believing the symptom.
- Separate the trigger from the cause; the deploy is rarely the bug.
Follow-up
- What would you look at first, and what would it rule out?
- How would you tell a cause from a coincidence here?
Built from the rounds and topics Mirage candidates report.
Prepare, practise & reflect
One practical outcome each day. Spend longer where you need it.
0 / 7 done01Map the Mirage loop
- Write out the reported sequence: Recruiter Call, Technical Screen, Onsite Interview.
- For each round, write one sentence on what it is judging, from the description above, and mark the one you are least ready for.
Deliverable: A one-page map of the 3 reported rounds, with the weakest marked.
02Work Backend Software Engineering
- Spend the session on Backend Software Engineering, which Mirage candidates report being tested on.
- Write one worked example in Backend Software Engineering and time yourself on it.
Deliverable: One timed worked example in Backend Software Engineering.
03Work Web Product Engineering
- Spend the session on Web Product Engineering, which Mirage candidates report being tested on.
- Write one worked example in Web Product Engineering and time yourself on it.
Deliverable: One timed worked example in Web Product Engineering.
04Work Applied AI Engineering
- Spend the session on Applied AI Engineering, which Mirage candidates report being tested on.
- Write one worked example in Applied AI Engineering and time yourself on it.
Deliverable: One timed worked example in Applied AI Engineering.
05Answer out loud: Algorithms and Data Structures
- Answer aloud, timed: Implement a rate limiter to throttle API requests based on user IP.
- Answer aloud, timed: Design an efficient in-memory cache with eviction policies like LRU or LFU.
Deliverable: Spoken answers to 2 reported Algorithms and Data Structures question(s), under time.
06Answer out loud: System Design and Architecture
- Answer aloud, timed: Design a real-time collaborative document editing system.
- Answer aloud, timed: How would you design a scalable notification system that supports SMS, email, and push notifications?
Deliverable: Spoken answers to 2 reported System Design and Architecture question(s), under time.
07Answer out loud: Frontend and Web Product Engineering
- Answer aloud, timed: Build a performant, reusable autocomplete search component using vanilla JavaScript or React.
- Answer aloud, timed: How do you optimize web application performance, specifically focusing on initial load time and rendering bottlenecks?
Deliverable: Spoken answers to 2 reported Frontend and Web Product Engineering question(s), under time.
Expand any day for tasks and deliverables. Your progress is saved on this device.
Behavioural rounds judge the decision you made and what it cost.
Describe a time when you had a technical disagreement with a peer or lead. How did you resolve it?
Describe a time when you had a technical disagreement with a peer or lead. How did you resolve it?
Approach
- Pick a story where you made the decision, not one where you watched it.
- State the situation in two sentences and spend the rest on the reasoning.
- Give the blast radius: what could have broken, and what you measured.
- Name the disagreement and how you resolved it with evidence.
Follow-up
- What would you do differently if you ran that again?
- How did you know your change caused the improvement?
Tell me about a complex technical project you owned from end to end. What were the trade-offs you had to make?
Tell me about a complex technical project you owned from end to end. What were the trade-offs you had to make?
Approach
- Pick a story where you made the decision, not one where you watched it.
- State the situation in two sentences and spend the rest on the reasoning.
- Give the blast radius: what could have broken, and what you measured.
- Name the disagreement and how you resolved it with evidence.
Follow-up
- What would you do differently if you ran that again?
- How did you know your change caused the improvement?
How do you prioritize technical debt versus shipping new features under tight deadlines?
How do you prioritize technical debt versus shipping new features under tight deadlines?
Approach
- Pick a story where you made the decision, not one where you watched it.
- State the situation in two sentences and spend the rest on the reasoning.
- Give the blast radius: what could have broken, and what you measured.
- Name the disagreement and how you resolved it with evidence.
Follow-up
- What would you do differently if you ran that again?
- How did you know your change caused the improvement?
How do you approach mentoring junior engineers or onboarding new team members?
How do you approach mentoring junior engineers or onboarding new team members?
Approach
- Pick a story where you made the decision, not one where you watched it.
- State the situation in two sentences and spend the rest on the reasoning.
- Give the blast radius: what could have broken, and what you measured.
- Name the disagreement and how you resolved it with evidence.
Follow-up
- What would you do differently if you ran that again?
- How did you know your change caused the improvement?
- 01
Describe a time when you had a technical disagreement with a peer or lead. How did you resolve it?
- 02
Tell me about a complex technical project you owned from end to end. What were the trade-offs you had to make?
- 03
How do you prioritize technical debt versus shipping new features under tight deadlines?
- 04
How do you approach mentoring junior engineers or onboarding new team members?
How technical is the interview process at Mirage?
The process is highly technical and practical. We focus on real-world engineering scenarios, system design, and coding proficiency rather than dry theoretical questions, ensuring a realistic assessment of your daily engineering capabilities.
Mirage Software Engineer candidate reports ↗What is the typical timeline from the first screen to an offer?
The entire process generally takes between two to four weeks. We strive to provide feedback within a few days of each round, keeping you updated throughout your candidate journey.
Mirage Software Engineer candidate reports ↗Can I choose my preferred programming language for the coding interviews?
Yes, you are welcome to use any mainstream programming language that you are most comfortable with, such as Python, Go, Java, or JavaScript, during the coding assessments.
Mirage Software Engineer candidate reports ↗Does Mirage support remote work or is it strictly on-site?
While we have a strong collaborative office culture in our New York, NY headquarters, we offer flexible hybrid working arrangements depending on the specific team and role requirements.
Mirage Software Engineer candidate reports ↗How should I prepare for the system design round?
Focus on understanding fundamental distributed systems concepts, database trade-offs, and horizontal scalability patterns. Practice mapping high-level business requirements to concrete architectural components.
Mirage Software Engineer candidate reports ↗What topics does Mirage test in interviews?
Mirage interviews most often cover Large Language Models (LLMs), SQL, Backend Software Engineering, PyTorch, and Multimodal Learning. The exact emphasis depends on the specific role you apply for.
Mirage Software Engineer candidate reports ↗Where is Mirage headquartered?
Mirage is headquartered in Paris, France.
Mirage Software Engineer candidate reports ↗Sources & methodology 3 sources ↗
Official role evidence, timestamped platform data and clearly labeled preparation advice.
- 01Mirage Software Engineer candidate reports ↗
Company-reported rounds, questions and FAQ.
candidate · Accessed 2026-09-22 - 02PracHub Software Engineer practice ↗
PracHub practice material, not company-reported.
platform · Accessed 2026-09-22 - 03PracHub preparation framework ↗
PracHub preparation guidance.
platform · Accessed 2026-09-22