tar_working_tree (walks repo + gzips several MB) and detect_git_sha (shells out) were called directly on the event loop, so /swarm-updates/push and /swarm-updates/push-self froze every other request until the tarball was ready. Wrap both in asyncio.to_thread.