--- src/lib.rs
+++ src/lib.rs
@@ -202,6 +202,7 @@
     tasks: RefCell<HashMap<u64, Py<PyAny>>>,
     next: Cell<u64>,
     sends: Cell<usize>,
+    eager_started: Cell<usize>,
     stopping: Cell<bool>,
     date: RefCell<Vec<u8>>,
     date_at: Cell<u64>,
@@ -620,7 +621,9 @@
                 .bind(py)
                 .call_method0(pyo3::intern!(py, "get_task_factory"))?
                 .is_none()
+                && self.eager_started.get() < 128
             {
+                self.eager_started.set(self.eager_started.get() + 1);
                 self.task_type
                     .bind(py)
                     .call((coro,), Some(self.task_options.bind(py)))?
@@ -1019,6 +1022,13 @@
             s.flush(py, &c)?;
         } else {
             return Err(PyValueError::new_err("Unsupported ASGI message"));
+        }
+        // Completing a response is a cooperative boundary. Do not delay scope
+        // cleanup after its bytes are already sent. Eager dispatch has its own
+        // per-callback budget, while unfinished producers retain the send budget.
+        if self.request.borrow().complete {
+            s.sends.set(0);
+            return Ok(s.done.clone_ref(py));
         }
         let n = s.sends.get() + 1;
         s.sends.set(n);
@@ -1231,6 +1241,7 @@
                 tasks: RefCell::new(HashMap::new()),
                 next: Cell::new(0),
                 sends: Cell::new(0),
+                eager_started: Cell::new(0),
                 stopping: Cell::new(false),
                 date: RefCell::new(Vec::new()),
                 date_at: Cell::new(0),
@@ -1249,6 +1260,7 @@
     fn poll(&self, py: Python<'_>) -> PyResult<()> {
         let s = &self.state;
         s.sends.set(0);
+        s.eager_started.set(0);
         for (token, mask) in s.poller.events()? {
             if token == 0 {
                 if s.stopping.get() {