Interview Experience

Meta E5 Backend, Phone Screen to Offer

A full-loop account of my Meta E5 backend interview, from cold-applying through team match, with the rounds and the calibration I missed.

Meta E5 Backend, Phone Screen to Offer

A full-loop account of my Meta E5 backend interview, from cold-applying through team match, with the rounds and the calibration I missed.

meta
interview-prep
system-design
coding-interview
behavioral
jameszhang

By @jameszhang

December 2, 2025

·

Updated May 18, 2026

466 views

4

Rate

I started the Meta loop on a Tuesday in late January and signed an E5 backend offer fourteen weeks later. I wrote this down for the version of myself that was reading every Meta interview thread the night before the phone screen, looking for one specific signal that nobody seemed to spell out. The signal I missed back then was that Meta's loop is calibrated, much more visibly than the other FAANG loops I went through, and that the calibration runs through the behavioral round in particular. The rest of this is the round-by-round, with the things I would change.

Timeline

Fourteen-week loop
  Week 0    Cold application via the careers site
  Week 1    Recruiter outreach, intro call (20 min)
  Week 4    Phone screen, two coding problems in 45 min
  Week 6    Onsite scheduling, prep guide sent
  Week 9    Onsite, five rounds across one and a half days
  Week 11   Hiring committee, recruiter calls with verbal offer
  Week 14   Team match closes, written offer signed

Four weeks between the recruiter call and the phone screen, and three weeks between the phone screen and onsite. That cadence is what I asked for. The default would have been faster. If you have any flexibility on timeline, ask for it. The marginal week is worth more than the marginal practice problem in week three.

The 45-minute phone screen, two problems and a tradeoff question

Forty-five minutes, two coding problems, one shared coding pad. The interviewer was an E5 from an infra-adjacent team. They opened with sixty seconds of context and then went straight to problem one.

Problem one was a moderate array problem. Sliding window with a twist on the validity condition. I narrated the brute force first, called out the complexity, and then wrote the optimized version. Around the eighteen-minute mark I had something passing the examples, including the two corner cases I had asked about up front. The interviewer ran a tougher example mentally, caught a bug in my updated window-shrink branch, and let me fix it.

Problem two was a graph problem disguised as a parsing question. I caught the graph framing in the second minute, said it out loud, and got the BFS down with about eight minutes to spare. The interviewer used the remaining time to ask a tradeoff question (when would you switch BFS to bidirectional). I gave a real answer with a concrete number, the threshold I had used in my previous job for a similar problem.

def shortest_path_bfs(graph: dict[str, list[str]], src: str, dst: str) -> int:
    if src == dst:
        return 0
    visited = {src}
    frontier = [src]
    depth = 0
    while frontier:
        depth += 1
        next_frontier = []
        for node in frontier:
            for neighbor in graph.get(node, []):
                if neighbor == dst:
                    return depth
                if neighbor not in visited:
                    visited.add(neighbor)
                    next_frontier.append(neighbor)
        frontier = next_frontier
    return -1

The single thing I would tell anyone prepping for the Meta phone screen: practice writing the BFS template by hand until you can do it without a single typo. The phone screen is two problems in forty-five minutes, which means a twelve-minute brute force and a ten-minute optimized solution, with reading time, follow-ups, and small-talk eating the rest. There is no slack in the budget for re-typing a queue.

How I Prepped Between the Phone Screen and the Onsite

Three weeks. I split the time roughly evenly between three buckets: coding template drills, system design, and behavioral.

For coding, I spent week one on Meta's tagged problem list, focusing on graphs and sliding window. Week two I added trees and dynamic programming. Week three I did one timed mock onsite per day, two coding rounds back to back, with a friend playing interviewer. I used a kitchen timer set loud enough that I could not ignore it. The kitchen timer was the prep change that helped most. Solving with a soft countdown timer in a browser tab is not the same kind of pressure as a physical timer at forty-five minutes ringing in another room.

For system design, I read two books in alternation, took notes by hand on one component per day, and built a personal failure-mode tree for the components I considered shaky (cache layers, message queues, rate limiters). I also did three system design mocks, one per week, with engineers I had worked with previously who agreed to push hard on whatever I went deep on.

For behavioral, I wrote ten stories down, in long form, and re-edited each one twice. Not three times, twice. Once for the structure (was the action clear, was the result quantified) and once for the failure mode (was I making myself sound too good). The failure-mode pass was the one that made the stories sound human instead of polished.

Onsite, five rounds across one and a half days

The onsite was five rounds across one and a half days. Two coding rounds, a system design round, a behavioral round (Meta calls it Jedi by tradition, though I never heard a real interviewer use the term), and a fifth round that depended on level. For E5 it was a second behavioral with a hiring-manager flavor. Each round was 45 minutes with 15-minute breaks.

Coding round one

A tree problem with a non-trivial recursion shape. The base case asked for a single property of the tree computable in one DFS pass. The follow-up turned it into a streaming problem: imagine the tree arrives one edge at a time, support the same query at any point, support deletions. I lost about six minutes trying to keep the original recursion working in the streaming variant before deciding to scrap and rewrite. The interviewer let me run with that decision.

The shape I should have reached for immediately was a small adjacency map plus an incremental aggregate, recomputed on the affected subtree only. The version I eventually landed looked like this in pseudocode:

class StreamingTreeAgg:
    def __init__(self):
        self.children: dict[int, list[int]] = {}
        self.parent: dict[int, int] = {}
        self.subtree_value: dict[int, int] = {}

    def add_edge(self, parent: int, child: int) -> None:
        self.children.setdefault(parent, []).append(child)
        self.parent[child] = parent
        # Recompute the aggregate up the chain.
        node = parent
        while node is not None:
            self.subtree_value[node] = self._recompute(node)
            node = self.parent.get(node)

    def _recompute(self, node: int) -> int:
        # Aggregate over children, plus this node's own contribution.
        return 1 + sum(self.subtree_value.get(c, 0) for c in self.children.get(node, []))

I ended this round one extension shy of where I thought I should have been. In the loops I sat through, this is the round where E5 candidates and E4 candidates separate the most: E5 is expected to land both the base case and at least one extension cleanly. I landed the base case cleanly and got partway through the extension. The recruiter later described this round as "on bar but not above it."

Coding round two

A harder version of a known pattern. I narrated the pattern out loud in the first minute, the interviewer nodded, and I implemented it without false starts. The follow-up was a complexity question with a real answer.

The pattern was a variant on a heap-plus-hashmap structure. The reason this round felt strong was that I had practiced this exact shape in my last week of prep: the index-and-priority pattern where a hash map points into entries inside a heap, so updates and deletions can be O(log n) without rebuilding the heap. I had typed the template enough times that the round was about narration, not about typing.

This round felt like the strongest of the day. The recruiter later confirmed it was the highest-graded round of the loop.

System design

Design a high-fan-out feed-style system. I had spent two weeks on system design prep and it showed. I drove the round in five chunks: requirements, capacity envelope, API shape, high-level data flow, then a deep dive on one component the interviewer picked.

I started by clarifying scope out loud: read-heavy versus write-heavy, latency target, consistency expectations, and what "feed" actually meant for this product. The interviewer confirmed read-heavy with bursty writes and a soft consistency target. From there I sketched the capacity envelope:

Capacity envelope, back-of-envelope
  DAU                100M
  Posts per user     2 / day, average
  Reads per user     100 / day, average
  Write QPS          ~2,300 sustained, ~10x peak
  Read QPS           ~115,000 sustained, ~3x peak
  Storage growth     ~100 GB / day for post bodies

Then the API shape, which I kept small on purpose:

API surface
  POST  /posts                  body, author_id           -> post_id
  GET   /feed?cursor=...        cursor, limit             -> posts page
  POST  /follow                 source_id, target_id      -> ok

With the envelope and API in front of us, the high-level data flow fit on the whiteboard cleanly: post writer -> append-only post store + an event for the fan-out workers, fan-out workers -> per-user feed cache, read path -> feed cache with fallback to a pull merge.

The interviewer picked the write path for the deep dive. We spent about twenty minutes on the write fan-out (push vs pull, hybrid, the celebrity problem), and I had a defensible take with the threshold (number of followers above which we switch from push to pull). I had a real number for that threshold, taken from a public engineering post I had read, with a citation in my head if asked.

The one thing I missed in the design round: I never drew the failure-mode tree. The interviewer prompted me twice to talk about what happens when a fan-out worker dies mid-batch and I gave answers that were thin. I now believe that for any backend design round at the E5 bar, you should have a failure-mode template ready (worker death, partial write, network partition, hot key) and apply it to whichever component you go deep on.

Behavioral, round one

Thirty-five minutes of stories, ten minutes of questions back at the interviewer. The interviewer ran four prompts: a conflict, a project I would do differently, a time I had to influence without authority, and a recent technical decision.

I had stories for the first three. The conflict story was a calibrated one with my previous tech lead about API ownership, told in roughly four minutes with a clear action and a measurable result (we ended up with a written charter that the team still uses). The would-do-differently story was a system rollout I had pushed too fast, with the post-rollout regression and the migration cleanup we did over the next two months. The influence-without-authority story was a cross-team library adoption that took five months and three failed attempts before the fourth attempt landed.

The fourth prompt I had not rehearsed. I picked a real one on the fly and the answer came out shapeless. I jumped between two different decisions, neither of them framed cleanly, and lost the action-versus-result thread by the third minute. The interviewer rescued it with a follow-up that pinned the question to a specific decision boundary, and I recovered, but it was the weakest fifteen minutes of my onsite.

The lesson is one I would not have predicted: the rehearsed stories were better, but the recovery on the unrehearsed one is what the interviewer wrote up most positively in the debrief. The recruiter told me later that the interviewer flagged the recovery itself as a positive signal, separately from the story content. Recovery from a shaky opening is gradable, and a skill worth practicing on its own.

Behavioral, round two (hiring manager flavor)

This round was framed differently. The interviewer was a director-level engineer and most of the conversation was about scope, ambiguity, and the kinds of problems I had owned end to end. The story bank that worked was the one where I could say, with numbers, what the state of the system was when I picked it up and what it was when I handed it off.

The Calibration I Missed

Meta calibrates the behavioral round more aggressively than the other FAANG loops I went through. The Jedi round in my loop, and from talking to friends who interviewed in the same window, was effectively scored against a rubric the interviewer is explicit about wanting to see, even if they will not show you the rubric directly. The four canonical buckets I now believe map to the rubric are:

  • Drives results: stories with numbers, end-to-end ownership, a measurable outcome
  • Drives direction: stories where you set or changed direction, not just executed on it
  • Communicates effectively: stories that demonstrate writing, calibrated escalation, or conflict navigation
  • Embraces ambiguity: stories where you operated without clear scope or with shifting goals

If you walk in with one strong story per bucket, including at least one failure story per bucket, you cover the rubric. If you walk in with seven stories that all live in drives results, you will get a flat behavioral score even if the technical rounds went well. I had two strong drives-results stories and one each in the others, and the gap showed up in the recruiter's debrief feedback.

Outcome and Team Match

Hiring committee approved on the first pass and the recruiter called with a verbal E5 offer four working days after the onsite. Team match took an additional three weeks. I spoke with five teams in that window. Two were a clear no from my side because the on-call shape was wrong for me, two were reasonable, and one was a strong yes.

I signed with the strong-yes team. The thing that made it the strong yes was a forty-five-minute call with the tech lead where they walked me through the actual on-call runbook for the team, page by page. Most team-match calls are recruiting-flavored. This one was substantive, and the substantive one is the signal you should be looking for.

The three prep changes that would have raised my onsite half a grade

Three things I would change about my prep, in order of impact:

  1. Rehearse the failure-mode tree for system design. I had the framework for the happy path. I did not have the template for failure modes. That cost me a half-grade on the design round.
  2. Write four behavioral stories per rubric bucket, not seven total. Coverage matters more than depth. Two of my stories were near-duplicates and that is wasted prep time.
  3. Practice typing the BFS / DFS / sliding-window templates without any errors. The phone screen has zero slack for typos.

The loop ended with an offer and I am at Meta now. The reason I wrote it down this way is that the things I would change were not visible to me from outside the loop. They became visible only in the recruiter debrief, which the recruiter will tell you about candidly if you ask the right question. The right question, in my experience, is: which round was lowest, and which one specific round-level signal would have raised it. Not what should I do better next time. The candid version comes only when the question is specific.