Python, Go, Rust, TypeScript and AI with Armin Ronacher

The Pragmatic Engineer 1h14 6 min #51
Python, Go, Rust, TypeScript and AI with Armin Ronacher
Watch on YouTube

Summary

  • Armin Ronacher is the creator of Flask, founding engineer at Sentry, and now building a new startup. He discusses how AI coding tools are reshaping software engineering, how to think about programming language tradeoffs for startups, what he learned about error handling from a decade at Sentry, and why the nature of programming languages may shift in an AI-assisted world.

The Python 2 to 3 migration and what it taught the ecosystem

  • The Python 2 to 3 migration was unusually painful and nearly damaged the language.
    • Python 3’s core motivation was stricter Unicode handling, but the real-world migration was far more complex than anticipated.
    • Early Python 3 releases (3.0, 3.1, 3.2) had design missteps, and the assumption that libraries could simply migrate once turned out to be wrong.
    • In practice, many libraries had to support both Python 2 and Python 3 simultaneously for years, sometimes over a decade.
    • The migration ultimately succeeded because the community accepted this dual-support reality rather than forcing a clean break.
  • The episode left a lasting lesson for other language ecosystems.
    • Rust, for example, explicitly cited Python 3’s migration as motivation for designing a system that lets codebases mix features from different language versions.

How Armin thinks about Python, Go, Rust, and TypeScript

  • His mental model splits into two modes: crafting open-source libraries versus building a product in a company.
    • For open-source craftsmanship, language design and API elegance matter a lot.
    • For a startup or company, what matters most is the product; the code is “write once, run many times,” not something you expect to keep rewriting against.
  • Python
    • Strong in infrastructure, provisioning, ML/data pipelines, and some web services.
    • Increasingly complex over time, which Armin now sees as a drawback for backend services.
    • He still expects every company to have some Python, but not necessarily as the main service language.
  • Rust
    • Excellent for binary data, load balancers, databases, single-binary distribution, predictable performance, and memory-safe concurrency.
    • Very good for extending Python when you hit performance or ecosystem integration problems.
    • Poor fit for most startups because of slow compile times, high code volume, and friction around the borrow checker and dynamic-type problems.
    • At Sentry, Rust was introduced pragmatically: first to solve performance problems inside Python, then for native symbol processing where the alternative would have been crash-prone C++.
  • Go
    • A pragmatic language for building web services and some CLI tools.
    • Armin chose it for his current startup because it scales well with AI coding tools: thin abstractions, easy for agents to understand, and more predictable output than Python or Rust.
    • He sees it as a good middle ground between Python’s flexibility and Rust’s strictness.
  • TypeScript / JavaScript
    • Unavoidable in the browser; on the server, Armin is conflicted.
    • He finds the language environment decent now, but the NPM ecosystem’s dependency burden is a major turnoff.
    • He prefers low-dependency setups and feels that server-side JavaScript forces him to manage too much dependency risk.
    • The traditional argument for a unified TypeScript codebase is weakening because code generation and API/SDK automation are improving rapidly.

How AI coding tools are changing Armin’s work

  • Armin was very negative about AI coding tools until around February–March 2025, then became strongly positive by May.
  • What changed his mind:
    • AI tools started doing work he hated but knew was necessary, such as debugging complex production issues involving multiple AWS permissioning errors.
    • He could make progress on his main task while Claude simultaneously investigated and fixed a production problem.
    • Tools like Claude became much better at creating minimal repro cases and bespoke internal tooling in minutes instead of weeks.
  • Current usage at his startup:
    • He and his co-founder work with Claude Code and OpenAI Codex as “AI interns.”
    • Over 80% of the codebase is agent-written: API endpoints, OpenAPI specs, and routine code that should be clean and well-tested but carries little unique information.
    • Even his non-technical co-founder uses Claude/Codex to build and validate core product experiences.
  • What AI changes and what it doesn’t:
    • Changed: cost of building custom tooling, speed of debugging, ability to search and learn unfamiliar topics, and the number of people who can now program with AI assistance.
    • Not changed: the need to understand architecture, maintainability, and system design; the value of human judgment about when generated code is right or wrong; and the importance of human energy and culture in a company.
  • He believes fully delegating everything to AI is risky because the edge comes from innovations not yet captured in training data.

Why programming languages still matter in an AI-driven world

  • Armin expects language choice to remain important, but the tradeoffs may shift.
    • Runtime characteristics and ecosystem fit still matter.
    • Some languages are clearly easier for AI agents to work with; in his experiments, Go produced better agent output than Python or Rust.
    • There may be room for a new language optimized for both human readability and AI generation/review.
  • He does not believe humans will leave the loop entirely.
    • If the output becomes too low-level or obscure, humans cannot review it.
    • The optimal tradeoff may actually move toward higher-level, more reviewable code.

The 996 work culture debate in AI startups

  • Armin observes that AI startups, especially in SF, are increasingly advertising extreme hours like 996 (9am–9pm, 6 days/week).
  • His take:
    • Agentic coding can feel addictive: instant gratification from kicking off another prompt, leading people to work through the night.
    • He went through a phase of unsustainable overwork himself, driven by excitement rather than necessity.
    • He strongly criticizes 996 as a label because it implies a rigid, life-consuming regimen with a negative history, including cases of severe health consequences.
    • He argues for high-intensity work that is still bounded and transparent about its costs, and he personally structures work around family and sustainable productivity.
    • He distinguishes between founders/early engineers with meaningful equity and later employees for whom such hours are much harder to justify.

What Armin learned about error handling from Sentry

  • The biggest lesson: errors in most ecosystems do not carry enough useful information in production.
    • Many errors are designed for debug builds, but the most important errors happen in production.
    • Language and runtime designers often neglect error richness because of performance costs.
  • Python was unusually good here: its introspection capabilities allowed Sentry to capture rich context like local variables without significant runtime penalty, which partly explains why Sentry started with Python.
  • Patterns across languages:
    • JavaScript errors are frequent but often low-impact; many are non-fatal and do not break the page.
    • C++ crashes are rare in well-built software, but when they occur, they are highly meaningful and often end the session.
    • This makes cross-language error rate comparisons misleading because the impact per error varies enormously.
  • Type safety and TypeScript:
    • Armin expected TypeScript to reduce JavaScript errors, but at Sentry’s scale, he saw no measurable impact on overall crash rates.
    • Increased system complexity, microservice version mismatches, and network-layer issues offset any gains from catching nullability errors at compile time.

Context locals and the hidden tradeoffs in language design

  • A recurring theme: seemingly small language or runtime decisions have large consequences for observability.
    • Example: context locals / execution context / async local storage are needed to propagate correlation IDs and tracing data through async code.
    • Stack frames carry this information naturally; async/await and promise chains do not, unless the runtime explicitly supports context propagation.
  • Another example: some native platforms gave up a stack pointer register for performance, making runtime stack unwinding and profiling much harder.
    • This hurt in-process profilers and tools like Sentry that need reliable stack traces.
    • Only recently did some Linux distributions reverse this decision, accepting a small performance hit for better debuggability.
  • Armin’s conclusion: language design is full of hard-to-quantify tradeoffs between performance, debuggability, and ecosystem needs, and there is rarely a single right answer.

Startup lessons and advice

  • From his time at Sentry and now founding a new company:
    • Early-stage startups are chaotic; roles are undefined, and you must be willing to do whatever comes up.
    • Some people thrive in that environment; others do not.
    • He deliberately thought more this time about what kind of company he wants to build and why, rather than just jumping in.
  • Advice for engineers joining early startups:
    • Be prepared for flux and ambiguity.
    • Either be comfortable doing whatever is needed, or be deliberate about steering your path even if it involves short-term tradeoffs.
    • Reading and podcasts help, but the experience of actually doing it is fundamentally different.

Rapid fire

  • Favorite programming language: Python, for both emotional reasons (it gave him his career) and pragmatic ones (he values what he can build with it, inspired by Kell Henderson’s pragmatic use of PHP at Flickr and Slack).
  • Favorite tool: a really good screwdriver, because high-quality tools make you more willing to take on physical work, which he sees as a metaphor for development tooling as well.
Back to The Pragmatic Engineer