Technical
Python Decorators I Actually Use in Production
Every Python tutorial eventually teaches decorators, and every junior engineer writes five clever ones they never use again. In production, I've converged on four decorators that show up in every project. Everything else is noise.
The Four
The four that survived:
- @cache / @lru_cache (stdlib) for expensive pure functions
- @property for computed attributes that should look like fields
- @router.post / @router.get (FastAPI) for HTTP handlers
- @retry (tenacity) for calls to flaky external services
That's it. I don't write custom decorators in application code anymore.
Why I Stopped Writing Custom Ones
Custom decorators hide control flow. A future reader sees @my_special_decorator and has to jump to its definition to understand what the function actually does. In five months of reviewing AI-generated code, the decorators the agent invents are almost always worse than a plain function call.
# What I see in AI suggestions
@timed_and_logged_and_authenticated
def handler(req):
...
# What I actually ship
def handler(req):
with_timing('handler')
auth.require(req)
...The second version is uglier and clearer. I pick clearer.
When a Custom Decorator Is Worth It
Library code where the decorator is the API. FastAPI's @router decorators are a great example: the decoration IS the registration. If removing the decorator would require inventing a different registration mechanism, keep it. Otherwise, call a function.
Full stdlib reference at the Python docs.
RELATED READING
The Consulting Shift I Am Making In Year Two
After a year of writing and building, my consulting practice is changing shape. Shorter engagements. Sharper outcomes.
ReadThe Frontend Shift: Shipping Less JavaScript In Year Two
A year ago I reached for Next.js for everything. This year I often reach for nothing.
ReadThe Serverless Lesson I Would Write On A Sticky Note
After a year of shipping serverless projects, one rule explains most of the wins and all of the losses.
Read