cn|
WorkWritingAboutConnect

cn

building things that matter

  • Work
  • Writing
  • About
  • Connect

© 2026 Cristian Najera

  1. Home
  2. /Writing
  3. /Why I Still Reach for Boring Python First
PythonOpinionEngineering

Why I Still Reach for Boring Python First

I default to stdlib and dataclasses until complexity is earned. Here is the heuristic I use to decide when a framework is worth the overhead.

July 21, 2026·3 min read

Every few weeks a new Python framework shows up on Hacker News. The benchmarks are impressive. The README is polished. The API looks elegant. And for about twenty minutes I genuinely consider rewriting whatever I am working on to use it. Then I close the tab, open a plain .py file, and get back to work.

This is not because new tools are bad. It is because the cost of adopting a tool is never just the time to install it. It is the time you spend learning its opinions, debugging its edge cases, and explaining its conventions to the next person who opens your code. For most problems I solve day to day, that cost is not worth paying.

The report that did not need a framework

Last year I needed an internal tool that pulled CSV exports from S3, ran a handful of transformations, and wrote a summary file back. Simple ETL, no users, no API, no database.

I opened my editor and started scaffolding a FastAPI project out of habit. Pydantic models for the row schema. An async S3 client. A proper project layout with src/, tests/, and a pyproject.toml. Ten minutes in, I stopped. There was no HTTP traffic to route. No request body to validate. No concurrent I/O worth optimizing. I was building infrastructure for a script.

I deleted the scaffold, created a single file, and used dataclasses for the row type, boto3 for the S3 calls, and csv.writer for the output. The whole thing was done in thirty minutes. It ran once a week via a cron job, and nobody ever had to think about it again.

The FastAPI version would have taken three hours and introduced five dependencies that needed security updates, version pins, and someone to remember why they were there. For a script with exactly one user — me — that overhead was irresponsible.

The three-things rule

I have a heuristic now. I add a framework when I need at least three things it provides, not one.

FastAPI earns its place when I need routing, request validation, and async I/O together. If I only need to validate some data, a few lines of manual checking or a dataclass with __post_init__ will do. Pydantic earns its place when I have untrusted external input, multiple interconnected models, and serialization requirements all at once. If I just need a typed container, dataclasses is right there in the standard library. SQLAlchemy earns its place when I have complex queries, relationship management, and migrations to coordinate. If I am reading from one table, a raw SQL query through sqlite3 is simpler and faster.

One reason is not enough. One reason means you are paying the full adoption cost of a framework to use a fraction of its surface area. That fraction almost always has a stdlib equivalent that is smaller, faster, and already installed.

Boring is a feature

None of this means frameworks are wrong. I use FastAPI almost every day. I reach for Pydantic constantly. But I reach for them on purpose, when I know exactly which three problems they solve for me in that specific project. The default is always the simplest thing that works — a plain function, a dataclass, a script that fits in one file.

The tools you do not add are the ones you never have to upgrade, never have to debug at two in the morning, and never have to explain to a junior engineer who just wants to understand what the code does. Boring Python is not a compromise. It is a feature.

0%
← PreviousEvals Are the Product

Related posts

The Case for Boring TechnologyWhy choosing well-understood tools leads to faster delivery and fewer surprises.1 min read
ArchitectureOpinion
RAG Pipelines at ScaleScaling retrieval-augmented generation from prototype to production with OpenSearch.1 min read
RAGPython
FastAPI Beyond Hello WorldDependency injection, middleware patterns, and production-ready error handling.1 min read
PythonFastAPI

Stay in the loop

New posts on engineering, architecture, and what I'm building.