Daniel sent us this one, and it starts with a pretty relatable moment. He's been using Raspberry Pis and single-board computers for a couple of years now, coming from a Linux background. Recently he wanted to build a smart clock display, something that syncs time over Wi-Fi and shows a couple of timezone readouts on an LED panel. And he realized, even a Raspberry Pi is overkill for that. That sent him down the ESP32 rabbit hole, and when he asked the obvious question, what operating system does the ESP32 run, he found out the answer is more interesting than he expected. The difference between a microcontroller and an SBC isn't just about which OS you pick. It's a fundamentally different tier of computing. And that made him think about all the smart devices out there with Wi-Fi connectivity that don't run Linux internally. Something, he admits, he'd never really considered before. So today we're going into the technical differences, RTOS versus full Linux, memory models, boot flow, the whole stack.
This is one of those topics where once you see it, you can't unsee it. You start looking at your thermostat or your smart light switch and thinking, there is a tiny computer in there doing something very specific and very deliberately constrained, and it has almost nothing in common with the Raspberry Pi sitting on your desk.
By the way, today's episode is powered by Claude Sonnet four point six. Just wanted to get that in early.
Anyway, the ESP32. Let's get into it.
Right, so the framing question Daniel was really asking is, what even is the difference between these two things at an architectural level. Because on the surface it sounds like a microcontroller is just a smaller, cheaper computer. And that framing is almost entirely wrong.
It's the wrong mental model from the start. An SBC like a NanoPi or a Raspberry Pi is a general-purpose computing platform. It has a processor, it has RAM as separate working memory, it has storage, and it runs a full operating system that manages all of that, abstracts the hardware, schedules processes, handles file systems. The whole apparatus.
Whereas the ESP32 is not running a general-purpose operating system in that sense at all.
The ESP32 is a microcontroller, which means it's a single integrated chip with a processor, memory, and peripherals all on-die. The Espressif ESP32 has two Xtensa LX6 cores, five hundred and twenty kilobytes of SRAM, and typically four megabytes of flash. That flash is not a hard drive in any meaningful sense. It's where your program lives. The SRAM is where it runs. There's no swap, no file system unless you explicitly implement one, no kernel managing processes.
When Daniel asked what OS the ESP32 runs, the honest answer is that the question almost doesn't apply. Or at least it applies very differently.
The honest answer is: it depends what you flash onto it. You can run FreeRTOS, which Espressif's own ESP-IDF framework uses by default. You can run bare-metal with no scheduler at all. What you cannot do is boot Linux in any conventional sense, because you don't have the memory headroom or the storage architecture to support it.
That's the tier distinction Daniel hit. It's not OS versus OS. It's OS versus something structurally prior to what we usually mean by OS—something like a real-time operating system.
And that's why the RTOS framing matters so much. FreeRTOS isn't Linux-lite. It's a real-time operating system, and the word real-time is doing actual technical work there. It means the scheduler makes hard guarantees about when a task will run. You give it a task with a priority and a timing constraint, and it will meet that constraint or the system has failed by definition.
Whereas Linux is making no such promise.
Linux is a multitasking OS optimized for throughput and fairness. The scheduler is trying to keep everything moving, but it's not guaranteeing that your Wi-Fi sync fires within five hundred microseconds of when you asked. On a Raspberry Pi running Raspbian, you have the kernel, you have systemd, you have dozens of background processes competing for CPU time. That's fine for most things. For a smart clock that just needs to update a display on a tight loop, it's genuinely unnecessary overhead.
On the ESP32, you're not fighting any of that.
You're not. FreeRTOS gives you tasks, not processes. There's no memory isolation between them, no virtual address space, no context-switching overhead from a full kernel. You write a task that polls the NTP server every sixty seconds, you write another task that refreshes the LED panel at thirty frames per second, you assign priorities, and FreeRTOS runs them in order. The whole scheduler fits in a few kilobytes.
That's actually a useful way to think about it. On Linux, the scheduler is this enormous piece of machinery designed to be fair to hundreds of competing processes. On FreeRTOS, the scheduler is basically just a sorted list. Highest priority task that's ready to run gets the CPU.
Right, and that simplicity is a feature, not a limitation. There's a classic way to think about this: Linux is a city with traffic lights and roundabouts and yield signs, all designed to keep thousands of cars moving through efficiently. FreeRTOS is a single intersection with a police officer who has a very clear list of who goes first. If the ambulance needs to get through, the ambulance gets through, every time, within a known number of microseconds.
For a clock display, you are the ambulance. The display refresh task cannot get stuck behind a kernel housekeeping process.
The real-time guarantee is the whole point. And that's why you find RTOS or bare-metal firmware in anything where timing actually matters physically. Industrial motor controllers, medical devices, anti-lock braking systems. Those aren't running Linux. They're running something with a deterministic scheduler because a missed deadline isn't just a bad user experience, it's a failure condition.
Let's talk about memory, because the numbers here are almost funny. Five hundred and twenty kilobytes of SRAM.
Against, say, five hundred and twelve megabytes on a NanoPi Neo, which is a pretty minimal SBC. That's roughly a thousand-to-one ratio. And the flash distinction is important too, because on the ESP32 that four megabytes is execute-in-place storage. The processor reads instructions directly from flash. There's no concept of loading an executable into memory from a disk. Your program is the flash.
The memory model isn't just smaller, it's structurally different.
On Linux, you have virtual memory, the kernel maps physical RAM into address spaces, processes think they have more memory than actually exists, you can have swap. On the ESP32, what you see is what you get. Five hundred and twenty kilobytes of SRAM, and you need to account for every byte. Stack size, heap allocations, the FreeRTOS kernel itself, your application buffers, the Wi-Fi driver stack which alone takes somewhere around a hundred kilobytes.
By the time you've loaded the Wi-Fi stack on an ESP32, you've used roughly a fifth of your available RAM.
Which is why memory-mapped peripherals matter so much at this tier. On Linux, you access hardware through device files. You write to slash dev slash something and the kernel handles it. On the ESP32, peripherals like the GPIO pins, the SPI bus, the I2C controller, they're literally memory addresses. You write a value to a specific address and the hardware responds. There's no driver layer in between.
How does that feel in practice when you're writing the code? Because coming from a Linux background like Daniel, that has to be a pretty jarring shift.
It's disorienting at first. On Linux you're insulated from the hardware by several layers of abstraction. You call a function, the function calls the kernel, the kernel talks to the driver, the driver talks to the hardware. On the ESP32 you're much closer to the metal. When you set a GPIO pin high, you are writing a bit to a register address. There's almost no indirection. The upside is you understand exactly what's happening and when. The downside is there's no safety net. If you write to the wrong address, you don't get a segfault and a helpful error message. You get weird behavior or a silent crash.
Which is also why debugging at this tier is a different skill.
On Linux you have gdb, you have strace, you have log files, you have a whole ecosystem of observability tools. On the ESP32 your primary debugging tool for a long time is a serial port and print statements. You're essentially printf-debugging a system with no terminal. There are JTAG debuggers and the ESP-IDF has decent tooling now, but the mental model shift is real. You have to hold more of the system in your head because the system won't tell you what went wrong.
That's also why boot time is what it is. The ESP32 is running in under a second.
Often under two hundred milliseconds from power-on to your application code executing. Because boot is just: initialize the hardware registers, load the bootloader from flash, jump to your application. There's no kernel decompressing, no init system, no service manager. A Raspberry Pi is taking thirty seconds minimum to reach a usable state, often more.
For a smart clock, that matters. You want the time on screen before someone notices the device rebooted.
That's actually where the knock-on effect start to compound, because boot time connects directly to power. If you're a thermostat, you're not plugged into a server rack. You're running on a transformer that's pulling maybe two watts from the wall. A Raspberry Pi at idle is drawing somewhere between two and five watts continuously. The ESP32 at full tilt, Wi-Fi active, both cores running, draws around two hundred and forty milliwatts. Deep sleep drops that to around ten microamps.
Ten microamps is essentially nothing.
It's rounding error on a coin cell. And that matters enormously for the economics of IoT at scale. If you're deploying ten thousand temperature sensors across a building, the difference between a five-watt device and a quarter-watt device is not a footnote. It's your infrastructure budget.
There's a fun way to think about that deep sleep number. Ten microamps at three volts is thirty microwatts. A CR2032 coin cell holds roughly two hundred and twenty milliamp-hours. If your device spends most of its time in deep sleep, waking up for a few hundred milliseconds every few minutes, you can realistically get a year or more of operation from a single coin cell. Try doing that with a Raspberry Pi.
You'd drain a car battery in a week. And this is why the deep sleep architecture on the ESP32 is so carefully designed. You can wake on a timer, on a GPIO interrupt, on a touch sensor event. The chip keeps a tiny low-power co-processor running that can monitor those wake sources while everything else is powered down. It's a fundamentally different design philosophy from an SBC, which assumes it's always on and always connected to mains power.
Which is part of why over seventy percent of IoT devices run on microcontrollers rather than SBCs. That number surprised me when I first saw it.
It shouldn't, once you do the math. The ESP32 itself costs somewhere between two and four dollars in volume. A NanoPi Neo is around eighteen to twenty-five dollars. For a smart thermostat that needs to read a temperature sensor, drive a small display, and hit an API every few minutes, you are not getting twenty dollars of value from the extra hardware.
The thermostat is a good case to sit with for a moment, because most people have one and most people have no idea what's inside it.
A modern smart thermostat, something like a mid-range connected unit, is almost certainly running a microcontroller, probably an ARM Cortex-M series or something in the ESP family. It has a temperature sensor wired directly to an ADC pin, an analog-to-digital converter, it has a small display driven over SPI or I2C, it has a Wi-Fi radio for cloud sync, and it has relay outputs to control the HVAC. The entire job of the software is: read sensor on a tight loop, compare to setpoint, toggle relay, sync schedule from cloud occasionally, update display. FreeRTOS handles that with room to spare.
There's no scenario where that thermostat needs a file system or a process scheduler.
And if someone shipped you a thermostat running a full Linux stack, you would rightfully ask what they were thinking. The boot time alone would be a user experience problem. You'd also be paying for it in the unit cost.
Although, to steelman the Linux approach for a second—there are smart home devices that do run Linux. Some of the higher-end hubs, certain routers that double as home automation controllers. Is there a version of that choice that makes sense?
Sure, when the device is doing more than one thing. A home automation hub that's running a local instance of Home Assistant, serving a web UI, managing dozens of device integrations, running automations with complex logic—that's a legitimate use case for a full Linux SBC. The software complexity is real and the Linux ecosystem helps. But that hub is also plugged into the wall, probably has active cooling, and costs a hundred and fifty dollars. It's not a thermostat. It's a server that happens to live in your living room.
Where does the ESP32 actually lose to something like a NanoPi? Because there has to be a line.
The line is roughly: anything that needs to process data rather than just react to it. Computer vision, audio processing beyond simple wake-word detection, running a local web server with meaningful logic, anything that wants a database. The ESP32 has no floating-point acceleration worth speaking of for heavy workloads, no Linux userspace, no package manager. You can't just apt-get your way to a solution.
The Arduino comparison is interesting here too, because a lot of people coming to ESP32 arrive from Arduino, and those are not the same thing.
They're in the same conceptual family but the ESP32 is considerably more capable. A classic Arduino Uno is running an ATmega328P, eight megahertz, two kilobytes of SRAM. The ESP32 has two hundred and sixty times the RAM, runs at up to two hundred and forty megahertz, and has Wi-Fi and Bluetooth built in. You can use the Arduino framework on an ESP32, Espressif supports it, but you're running Arduino-style code on top of a much more powerful chip. The abstraction is the same, the hardware underneath is not.
The Arduino framework is essentially a programming model, not a hardware constraint.
ESP-IDF, Espressif's native framework, gives you direct access to FreeRTOS, all the peripheral APIs, the full Wi-Fi stack. The Arduino layer on top of that trades some of that control for familiarity. For Daniel's smart clock, either would work. For something pushing the ESP32's limits, you'd want to be closer to ESP-IDF.
How would you describe that tradeoff to someone trying to decide which entry point to use?
Arduino is the on-ramp. It hides a lot of the FreeRTOS machinery behind a simple setup-and-loop model. You write your setup function, you write your loop function, and the framework handles the rest. That's great for getting something working quickly. ESP-IDF is the full highway. You're explicitly creating FreeRTOS tasks, managing your own memory, configuring the Wi-Fi stack directly. There's more boilerplate, more to understand, but you have control over everything. For someone coming from Linux, ESP-IDF will actually feel more familiar in some ways, because you're dealing with explicit concurrency and resource management rather than a simplified abstraction.
Which connects back to the scalability question. If you're a developer building a product, the ESP32 tier gives you something you cannot get from an SBC: predictability at low cost across thousands of units.
Deterministic behavior, low power, sub-dollar bill-of-materials contribution in volume, and a toolchain that fits on a laptop. The barrier to shipping an IoT product on an ESP32 is meaningfully lower than shipping one on a Linux SBC, not just in hardware cost but in the software complexity you're managing. So when choosing between these tiers, those factors really define the starting point.
Right, and for someone listening who's trying to figure out which tier they actually need, what does that decision tree look like?
The first question is power. If your device is battery-powered, or if it's running off a small wall adapter and you care about the electricity bill at scale, you're almost certainly in microcontroller territory. The ESP32's deep sleep current is so low it's essentially free to run on a small lithium cell for months. Nothing in the SBC world comes close to that.
Cost is the second gate.
Cost and quantity together. If you're building one device for yourself, the price difference between a four-dollar ESP32 and a twenty-dollar NanoPi is not going to change your life. If you're thinking about a product, or deploying more than a handful of units, that gap compounds fast.
The third gate being: does your device actually need Linux?
That's the honest question to ask. Not "would Linux be convenient" but "does this task require a process scheduler, a file system, a network stack with full TCP support, or the ability to run arbitrary software?" If the answer is yes to any of those, reach for the SBC. If the answer is "I need to read a sensor and push data somewhere every thirty seconds," the ESP32 will do that better, cheaper, and with less power than anything running a full OS.
For someone who wants to actually get their hands on an ESP32, the barrier is low.
It's very low. An ESP32 development board is a few dollars, the ESP-IDF toolchain installs on any machine, and if you want the gentler on-ramp, the Arduino framework on ESP32 is well-documented. Daniel's smart clock is a real project anyone could complete in a weekend. Wi-Fi time sync over NTP, a small LED matrix, FreeRTOS handling the display refresh loop. The whole thing costs less than a decent lunch.
The thing you learn from building it is what Daniel described: the tier distinction clicks into place once you've written code that runs without an OS underneath it. It's like a lightbulb moment.
And once that clicks, you start seeing it everywhere—the thermostat, the garage door opener, the scale in your bathroom that reports your weight to an app. None of those are running Linux. They never were.
Which raises the question I keep coming back to: does that tier stay stable? Chips get cheaper, flash gets denser. At some point does the microcontroller tier just...
It's a interesting pressure. The ESP32-S3 already has enough grunt to run basic neural network inference. There are RISC-V based microcontrollers pushing into territory that would have required a full SBC five years ago. But I'm not sure the answer is convergence. I think the power envelope keeps them separated. The moment you add the memory management unit and the full Linux stack, you've made a set of architectural choices that cost power. The SBC and the microcontroller are optimized for different things at a pretty fundamental level.
It's less "microcontrollers catching up" and more "the boundary shifting while the gap stays.
That's probably the right frame. The capabilities at each tier expand, but the tier distinction itself, deterministic real-time execution versus general-purpose multitasking, that doesn't dissolve just because the chips get faster. And there's actually a historical parallel here worth noting. People said the same thing about eight-bit microcontrollers when sixteen-bit chips arrived, and then again when thirty-two-bit ARM Cortex-M parts came along and cost less than a dollar. The prediction was always that the simpler tier would disappear. It never did. The use cases that fit the constraints just kept expanding to fill the new capabilities, and the fundamental architectural split stayed intact.
The cheap tier gets more powerful but it doesn't stop being the cheap tier.
Right, because the expensive tier gets more powerful too. And the question I'd leave open is what happens to the middle. There are chips like the ESP32-S3 and some of the newer Nordic silicon that are starting to blur the line in interesting ways.
Something to watch. Thanks to Hilbert Flumingtop for producing this one, and to Modal for keeping the compute running so we can keep making the show. This has been My Weird Prompts. If you've got a minute, a review goes a long way, find us on Spotify and leave one there.
We'll see you next time.