Person/Gergely Orosz/Podcast/25/10/Python Go Rust Typescript AI Armin Ronacher
Properties
Python, Go, Rust, TypeScript and AI with Armin Ronacher
- On how Armin uses AI tools (at 28:05) and how he switched from Terraform to Pulumi
“Over the years, many of my projects didn’t go anywhere because the legwork needed to build this bespoke tooling to be able to pull this project off was too much.
One of the big changes I’m noticing for myself is that I have so many better tools around now. For example, I moved from Terraform to Pulumi for one of the services just to see how that goes. I had Claude build me a perfect control system to get my logs and visualize what’s going on in production. I would never have done this before [Claude Code] just because it wouldn’t have worked.” - #Quote from Person/Armin Ronacher
- Why Armin doesn’t believe strongly typed languages like Typescript meaningfully reduce errors — based on his experience observing this at Sentry (at 52:42:)
"There was a large-scale realization in JavaScript ecosystem that type checkers could get rid of a whole class of errors, because at the very least you have to explicitly check if this thing is nullable or not.
I never got the feeling that the adoption of TypeScript dramatically changed anything about JavaScript error rates. None of that adoption had any meaningful impact. If there was an impact, it’s immeasurable.
I remember that the adoption of more and more complex things in the React ecosystem has just dramatically increased the types of errors. For example, hydration errors were not a thing for many years. And then all of sudden, there’s a whole class of new errors coming in because of this [because of the wider adoption of React.]" - #Quote from Person/Armin Ronacher
- Choose languages pragmatically for the product and team, not ideology; even modern Java can be great with virtual threads as part of a practical stack pragmatic language choice.
- Python remains unavoidable for ML, data, and infra, though it’s grown in complexity; Go is often easier for high‑throughput services today state of the Python ecosystem.
- Rust
- Rust shines as a pragmatic way to extend Python and for binary/WebAssembly work where memory layout and single‑binary trade‑offs matter Rust’s pragmatism for extensions.
- For early‑stage startups, Rust’s precision adds friction (compile times, strict types, borrow checker); Go often hits the speed/iteration sweet spot why Rust can slow startup iteration.
- AI changes language trade‑offs: thin abstractions help agents; measured runs showed #Go codegen passing more often than #Python or #Rust thin abstractions help AI produce better code.
- Expect #Python and #TypeScript to appear somewhere in your stack regardless; the question is how much of your code lives in them plan for languages you can’t avoid.
- #TypeScript on the backend is hampered by the NPM ecosystem’s heavy dependency sprawl, which can undermine control and confidence TypeScript drawbacks on the server.
- Prefer modern #Codegen and OpenAPI‑driven SDKs over forcing a single language across front‑ and back‑end boundaries use codegen over a unified codebase.
- AI coding tools now handle boilerplate and “run‑of‑the‑mill” tasks (endpoints, OpenAPI), freeing engineers to focus on authentic, core code—and even enabling quick bespoke tools you’d never have built before how AI coding tools boost productivity.
- Agents are powerful but can feel like a slot machine—addictive and unsustainable if you’re always “kicking it off again” the slot‑machine effect of agent chains.
Good Error Reporting is a Deliberate Practice
- Good error reporting is a deliberate practice; languages/runtimes should carry richer production context, and Context Locals are crucial when Async Programming async/await breaks stack‑based propagation errors need richer production context.
- Errors often lack rich, production-friendly context because runtimes and languages trade debuggability for performance.
- Better language/runtime support for rich error data would greatly improve debugging but requires deliberate design choices.
"The biggest thing that I learned... is that many of the ways in which errors are worked with just don't carry enough information or only carry useful information for debugging in debug builds. And that's problematic because the most interesting errors don't happen in debug... As a language designer, as a VM creator, you should put a lot more emphasis on making sure that the errors can carry really useful information rather cheaply even in reduced and in production runs. Not a lot of ecosystems do that, which is very sad... Python had such great introspectability... That actually was the reason Sentry existed. Because Sentry was able to show local variables for Python. It had all this rich, powerful data that for many languages, even today, we're not able to do because the runtime doesn't support it... Your experience of debugging issues is so much better if you have rich information in errors. And unfortunately, both languages, language creators, runtimes often neglect errors." - #Quote from Person/Armin Ronacher
- Context Locals provide storage that flows with the logical flow of execution, allowing correlation IDs and tracing data to propagate through async/await or promise chains without explicit passing at each step.
- The problem: Stack frames implicitly carry information (correlation IDs, tracing context), making it trivial to access by walking up the stack. With async/await or promises, this stack context is lost because execution is chained across promises.
"The immediate problem that we have, if you start moving towards promises, is that now it's very hard to carry through information through all of the potential paths that this promise chain would take you. So for instance, if you want to say like I have a correlation ID, which should be attached to every single log event, it should be attached to every single error event, that might happen as a result of this original thing I'm doing. With stack frames, super trivial. It's sitting somewhere in a stack. I will not lose it. I can walk up the stack and find it again. But with promises, now I need to have this chain together. And so context locals is what is called in some languages... It's basically a hidden piece of almost like a thread local, but a much more narrow scoped one, which flows with the logical flow of execution. And why is this necessary? Because if you do something like OpenTelemetry, if you do tracing, if you do things like you want to have a correlation ID, you want to have it show up everywhere, right?" - #Quote from Person/Armin Ronacher
Language Support
- Good error reporting is a deliberate practice; languages/runtimes should carry richer production context, and Context Locals are crucial when Async Programming async/await breaks stack‑based propagation errors need richer production context.
- As systems and teams scale, language adoption is a trade‑off game; sometimes you introduce a new language for performance or ecosystem fit, not purity language adoption trade‑offs at scale.
- On how Armin uses AI tools (at 28:05) and how he switched from Terraform to Pulumi