Explain Dart's event loop, microtask queue, event queue, and await behavior

Tests Dart single-threaded event loop model. Strong answer: microtasks drain before event queue tasks; await suspends the function and schedules its resumption via the event loop when the Future completes. Red flag: claiming await blocks the thread.
What's really being asked
Your grasp of Dart's single-threaded event-driven architecture inside a single isolate. The interviewer wants to know if you understand that Dart concurrency is cooperative rather than preemptive, and that async-await is syntactic sugar over Future callbacks scheduled on the event loop. They are checking whether you can reason about frame jank, timer precision, and microtask starvation.
The full answer
First, that every isolate has exactly one event loop and two queues: the microtask queue and the event queue. Second, that the event loop's only job is to pick the next task to run, and it always empties the entire microtask queue before looking at the event queue. This means microtasks can starve the event queue if they keep rescheduling themselves. Third, that the event queue contains external events like user input, file I/O completions, and timers, while the microtask queue handles internal short async work such as Future.value resolution and async/await bookkeeping. Fourth, that awaiting a Future splits the async function at the await boundary. The code after await becomes a closure attached to that Future, the function immediately returns an incomplete Future to its caller, and when the awaited Future completes, its continuation is enqueued on the event loop rather than executed instantly. Fifth, that because all of this happens on a single thread per isolate, no two Dart callbacks run in parallel within the same isolate.
The mistakes people make
Saying that await blocks the thread or pauses the isolate. It does not block; it yields control and the event loop keeps spinning. Claiming that microtasks and event queue tasks interleave one-for-one. They do not; microtasks always batch-drain first. Stating that the rest of the function runs synchronously right after the Future resolves. In reality it is scheduled as an event-loop task. Describing threads instead of isolates. Dart uses isolates, not shared-memory threads, for parallel work.
What usually comes next
How does Future.microtask differ from a normal Future constructor? What happens if a microtask recursively schedules more microtasks? How would you move heavy computation off the main isolate? Why might a Timer.periodic drift when the event loop is busy? How does the event loop relate to Flutter's build, layout, and paint pipeline?
A concrete example
Imagine an async function that prints A, awaits a Future.delayed of one second, then prints B. When called, A prints immediately because it runs synchronously up to the await. The await causes the function to return an incomplete Future to its caller. After one second, the timer puts a completion task on the event queue. The event loop eventually picks it up, and the continuation prints B. If you had inserted Future.microtask(() => print C) before the await, C would print before A's function even suspended, because microtasks run before the next event-loop turn.
Interview question
In a Dart isolate, what is the consequence of a microtask that keeps rescheduling new microtasks recursively?
- a.The event queue is starved until the recursive microtask chain endsCorrect
- b.The recursive microtasks are moved to the event queue to prevent starvation
- c.The event loop alternates between one microtask and one event queue task
- d.The isolate crashes with a stack overflow after 1000 recursive microtasks
Why? this is the answer
The event loop always drains the entire microtask queue before processing any event queue tasks, so a self-rescheduling microtask chain blocks the event queue indefinitely. Option C is wrong because Dart does not interleave the two queues one-for-one.
Just read this? Test yourself on what you have been reading.
Read the original → dart.dev
You just looked this up. Could you explain it out loud?
That is the part interviews actually test. Tezvyn takes questions like this one and gives you what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.
We are hiring for this. Open roles that interview on dart — each one lists the topics its interview covers.
See open roles