惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

MyScale Blog
MyScale Blog
量子位
宝玉的分享
宝玉的分享
爱范儿
爱范儿
云风的 BLOG
云风的 BLOG
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Recent Announcements
Recent Announcements
Apple Machine Learning Research
Apple Machine Learning Research
N
News and Events Feed by Topic
TaoSecurity Blog
TaoSecurity Blog
博客园 - 三生石上(FineUI控件)
小众软件
小众软件
Simon Willison's Weblog
Simon Willison's Weblog
Google DeepMind News
Google DeepMind News
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
aimingoo的专栏
aimingoo的专栏
Cloudbric
Cloudbric
Blog — PlanetScale
Blog — PlanetScale
Latest news
Latest news
S
Security @ Cisco Blogs
Last Week in AI
Last Week in AI
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Vercel News
Vercel News
W
WeLiveSecurity
M
MIT News - Artificial intelligence
P
Proofpoint News Feed
P
Proofpoint News Feed
P
Palo Alto Networks Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
T
The Blog of Author Tim Ferriss
腾讯CDC
大猫的无限游戏
大猫的无限游戏
Martin Fowler
Martin Fowler
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
V
V2EX
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Stack Overflow Blog
Stack Overflow Blog
IT之家
IT之家
有赞技术团队
有赞技术团队
Microsoft Security Blog
Microsoft Security Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
美团技术团队
博客园 - 【当耐特】
D
DataBreaches.Net
I
InfoQ
G
GRAHAM CLULEY
S
SegmentFault 最新的问题
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
B
Blog

Pierce Freeman

A browser for agents | Pierce Freeman The grey market of podcast appearances The way I travel | Pierce Freeman Fixing slow AWS uploads | Pierce Freeman Local tools should still use vaults We solved scratch content first Starting a podcast in 2025 Being late but still being early Automating our home video imports Adding my parents to tailscale A deep dive on agent sandboxes Language servers for AI | Pierce Freeman My simple home podcast studio We need centralized infrastructure | Pierce Freeman Coercing agents to follow conventions using AST validation My unified theory of social selling My personal backup strategy | Pierce Freeman July updates to the homelab How the KV Cache works httpx is the right way to do web requests in Python Reputation is becoming everything | Pierce Freeman Building a (kind of) invisible mac app Updated knowledge in language models Making an ascii animation | Pierce Freeman How speculative decoding works | Pierce Freeman Under the hood of Claude Code Doing things because they're easy, not hard Speeding up sideeffects with JIT in mountaineer Misadventures in Python hot reloading How text diffusion works | Pierce Freeman The tenacity of modern LLMs The ergonomics of rails | Pierce Freeman How language servers work | Pierce Freeman Just add eggs | Pierce Freeman Unfortunately SEO still matters | Pierce Freeman The futility of human-only web requirements Setting up Input Leap | Pierce Freeman Checking in on Waymo | Pierce Freeman The react revolution | Pierce Freeman Speeding up many small transfers to a unifi nas Quick notes on swift libraries AI engineering is a different animal San Francisco | Pierce Freeman Debugging a mountaineer rendering segfault Local network config on macOS Building our home network | Pierce Freeman Introducing Envelope.dev | Pierce Freeman Legacy code and AI copilots Typehinting from day-zero | Pierce Freeman Generating database migrations with acyclic graphs Lofoten | Pierce Freeman Mountaineer v0.1: Webapps in Python and React Constraining LLM Outputs | Pierce Freeman Passthrough above all | Pierce Freeman Accuracy in kudos | Pierce Freeman How quick we are to adapt The curious case of LM repetition Costa Rica | Pierce Freeman Debugging chrome extensions with system-level logging Speeding up runpod | Pierce Freeman Inline footnotes with html templates Parsing Common Crawl in a day for $60 An era of rich CLI All or nothing with remote work The Next 10 Years | Pierce Freeman Adding wheels to flash-attention | Pierce Freeman LLMs as interdisciplinary agents | Pierce Freeman New Zealand | Pierce Freeman Representations in autoregressive models | Pierce Freeman Let's talk about Siri | Pierce Freeman Minimum viable public infrastructure | Pierce Freeman Reasoning vs. Memorization in LLMs Automatically migrate enums in alembic Greater sequence lengths will set us free On learning to ski | Pierce Freeman Dolomites | Pierce Freeman Using grpc with node and typescript Opportunity years | Pierce Freeman Buzzword peaks and valleys | Pierce Freeman Buenos Aires | Pierce Freeman Network routing interaction on MacOS Independent work: November recap | Pierce Freeman Debugging slow pytorch training performance The provenance of copy and paste Debugging tips for neural network training Patagonia | Pierce Freeman Santiago | Pierce Freeman My 2022 digital travel kit AWS vs GCP - GPU Availability V2 Independent work: October recap | Pierce Freeman Planning Patagonia | Pierce Freeman Relationship modeling | Pierce Freeman The power of status updates A new chapter | Pierce Freeman Give my library a coffee shop AWS vs GCP - GPU Availability V1 Switzerland | Pierce Freeman Headfull browsers beat headless | Pierce Freeman Webcrawling tradeoffs | Pierce Freeman Copenhagen | Pierce Freeman
Firehot for hot reloading in Python
2025-06-24 · via Pierce Freeman

header

I've spent a lot of time thinking about hot reloading in Python. Firehot is my answer to that problem for web development.

We can make a pretty simple observation about import dependencies: during development, your third-party dependencies (Django, Flask, requests, SQLAlchemy) almost never change. It's only your project code that's constantly being modified. So why restart everything when you could just restart the parts that actually change?

The approach in firehot works by process isolation. If you're careful with how you do it, a fork() in Unix will copy the exact runtime state into a fresh process. A Python interpreter is actually a pretty simple application executable to copy - it's single threaded and uses the GIL for locking C code. We can build up a Python process that preloads all of our third party sys.modules imported anywhere in our project. When our actual code hits that import it will be a no-op because it has already imported the bytecode.

The result is that when you change your project code, only your project modules get reloaded. The expensive third-party imports (Django, NumPy, etc) stay loaded and cached. Startup time can drop from 5+ seconds to 200ms.

Here's what a typical reload cycle looks like:

from firehot import isolate_imports
from os import getpid, getppid

def run_under_environment(value: int):
   parent_pid = getppid()
   print(f"Running with value: {value} (pid: {getpid()}, parent_pid: {parent_pid})")

# Scan through the current package and determine all imports
# Load these into a template environment that we can fork()
with isolate_imports("my_package") as environment:
   # Each exec will be run in a new process with the environment isolated, inheriting
   # the package's third party imports without having to re-import them from scratch.
   context1 = environment.exec(run_under_environment, 1)

   # These can potentially be long running - to wait on the completion status, you can do:
   result1 = environment.communicate_isolated(context1)

   # If you change the underlying my_project files on disk to add an import, you can run update_environment.
   environment.update_environment()

   # Subsequent execs will use the updated environment.
   context2 = environment.exec(run_under_environment, 2)
   result2 = environment.communicate_isolated(context2)

My mental model for this pipeline is like Dockerfiles: you build up each individual layer with package dependencies. If you need to reload any of them, you just need to unroll layers1 until you reach the one where they were declared and rebuild it.

The Import Tax

Python's import system has always been designed for production environments where you start once and run forever. But this creates an import tax that your dev workflow has to bear. You pay the fixed cost you pay every time your application boots. The tax gets higher as your dependency tree grows.

Modern Python applications routinely import hundreds of packages at startup. Each package can trigger its own initialization logic: database drivers establishing connection pools, ML libraries loading models into memory, web frameworks scanning for route definitions. What started as simple import requests statements compound into multi-second delays.

The conventional wisdom has been to live with it. "Just use gunicorn in production and accept the slow development cycle." But this feels backward. We've optimized for the 0.1% of time when code boots up in production at the expense of the 99.9% of bootup time when developers are iterating.

Firehot flips this equation. Instead of paying the import tax on every restart, you pay it once per session. The template process becomes your cached dependency state, and forking becomes your reload mechanism.

Why Fork Works

Python's import system is largely read-only after initialization. Once sys.modules is populated, imports become dictionary lookups. This is annoying if you're trying to manipulate the runtime imports but works pretty nicely in a forking context. The mutability of imports and isolation of forked processes let clients inherit the full import state without corrupting the parent.

If your updated code introduces a new third-party import, Firehot detects this via AST parsing and knows to rebuild the template process. If you just changed business logic, it skips the expensive rebuild and forks immediately.

This creates a performance profile that matches your development workflow: fast iterations for code changes, slower rebuilds only when you actually change dependencies. Most development sessions involve hundreds of code tweaks for every new package added.

The Rust Bridge

Writing this in pure Python would be possible but painfully slow. Python's subprocess management and AST parsing are decent, but not optimized for the tight loops that hot reloading demands. Every millisecond matters when you're trying to stay in flow state.

Firehot is mostly written in Rust, especially for the performance-critical paths: file watching, process management, and dependency analysis. Python handles the higher-level orchestration and API surface. It's the same pattern that's made tools like ruff and uv so much faster than their pure-Python predecessors. AST parsing is blazing fast in the Rust ecosystem.

The architecture also means Firehot can work with any Python web framework or application structure. It doesn't need to understand Django's auto-reloader or Flask's debug mode - it operates at the import level, which is universal across Python applications.

In practice, this feels like having your cake and eating it too. You get the ergonomics of rapid development cycles without sacrificing the rich ecosystem that makes Python productive in the first place. The expensive imports happen once, then fade into the background where they belong.

  1. Processes for Firehot, filesystem layers for docker. ↩