The RTOS landscape for IoT has consolidated around three open-source options that dominate production deployments: FreeRTOS (backed by AWS), Zephyr (backed by the Linux Foundation), and NuttX (an Apache project, notably used by Sony and Samsung). Each makes fundamentally different architectural choices that affect everything from minimum footprint to developer ergonomics to long-term maintainability.

This comparison focuses on the engineering tradeoffs that matter for shipping IoT products — not benchmark scores in isolation, but how each RTOS handles the full lifecycle from initial bring-up through OTA firmware updates in production fleets.

Kernel Architecture

FreeRTOS is a microkernel in the purest sense: the core provides task scheduling, synchronization primitives (semaphores, mutexes, queues, event groups), software timers, and nothing else. Networking, filesystems, and TLS are separate libraries (FreeRTOS+TCP, FreeRTOS+FAT, etc.) that you integrate as needed. This modularity keeps the base footprint under 6 KB of flash.

Zephyr takes a monolithic approach with aggressive configurability. The kernel, drivers, networking, Bluetooth, and security subsystems are all part of the same source tree, compiled via Kconfig/CMake. You include what you need, and the build system strips everything else. This integration means subsystems are tested together and share consistent APIs, at the cost of a steeper learning curve.

NuttX is POSIX-oriented. Its kernel implements a Unix-like abstraction layer with file descriptors, virtual filesystem (VFS), device nodes, sockets, and pthreads. Applications interact through standard POSIX system calls rather than RTOS-specific APIs. This makes NuttX the easiest target for porting Linux userspace code, but the abstraction layer adds overhead that makes the minimum footprint larger than FreeRTOS or Zephyr.

Kernel Architecture Comparison FreeRTOS Application Code +TCP +TLS Microkernel Tasks · Queues · Timers Vendor HAL / BSP ~6 KB flash min Zephyr Application Code Monolithic Kernel Scheduler · Drivers · BLE Net Stack · TLS · Logging Kconfig-selectable subsystems Device Tree + HAL ~8 KB flash min NuttX POSIX Application VFS · Sockets · pthreads File descriptors · Signals POSIX Kernel Flat / Protected / Kernel modes Architecture-specific BSP ~32 KB flash min Each architecture trades simplicity against integration depth and API compatibility

Scheduling and Real-Time Guarantees

All three RTOSes provide preemptive priority-based scheduling — the highest-priority ready task always runs. The differences lie in additional scheduling policies and priority inversion mitigation.

FreeRTOS supports configurable time-slicing for equal-priority tasks and provides priority inheritance on mutexes to prevent unbounded priority inversion. The scheduler is simple and predictable — context switch time on a Cortex-M4 at 168 MHz is typically 2-4 microseconds.

Zephyr adds cooperative scheduling modes (useful for ultra-low-power states), workqueues for deferred interrupt processing, and a polling subsystem that lets threads wait on multiple event sources simultaneously. Zephyr also supports tickless idle, which eliminates periodic timer interrupts during sleep to minimize power consumption.

NuttX supports both flat and protected build modes. In protected mode, kernel and user spaces are separated using the MPU, providing memory protection between tasks — a feature that neither FreeRTOS nor Zephyr offers in their standard configurations. This makes NuttX attractive for safety-critical applications where task isolation is required.

Memory Management

Memory management philosophy differs sharply between the three:

FeatureFreeRTOSZephyrNuttX
Heap allocators5 schemes (heap_1 to heap_5)k_malloc + memory poolsStandard malloc/free
Static allocationSupported (configMeomry static)Native (preferred)Supported
Memory poolsManual via queuesk_mem_slab, k_mem_poolStandard via VFS
MPU supportBasic (stack overflow only)Thread stack protectionFull protected mode
Stack analysisuxTaskGetStackHighWaterMarkCONFIG_THREAD_ANALYZER/proc/pid/status

FreeRTOS gives you the most control — heap_1 allocates but never frees (useful for static systems), while heap_4 provides a general-purpose allocator with coalescence. Zephyr's memory slabs provide deterministic allocation for fixed-size objects, making them ideal for MQTT message buffers and network packet pools. NuttX's standard malloc interface is the most familiar but the least deterministic.

Networking Stacks

Networking is where the architectural differences matter most for IoT applications. FreeRTOS provides FreeRTOS+TCP, a lightweight IPv4 stack, but it lacks native IPv6, Bluetooth, Thread, and LoRaWAN support. Teams typically integrate third-party stacks (lwIP, NimBLE) for these protocols, which requires glue code and increases maintenance burden.

Zephyr's networking subsystem is the most comprehensive. It includes native IPv4/IPv6 dual-stack, TCP/UDP sockets, CoAP, MQTT, HTTP client, DNS resolver, mDNS/DNS-SD, Bluetooth LE (including Mesh), Thread/OpenThread, IEEE 802.15.4, and LoRaWAN — all integrated with the kernel's threading model and tested together in CI.

NuttX provides a BSD-compatible socket interface over its own lightweight IP stack. The socket API familiarity makes porting network-heavy Linux applications straightforward, but the protocol coverage is narrower than Zephyr's — Bluetooth and Thread support are less mature.

Device Driver Model

FreeRTOS has no formal driver model. Drivers are typically provided by silicon vendors as part of their HAL/SDK (STM32 HAL, ESP-IDF, Nordic nRF SDK) and integrated directly into the application. This works well when targeting a single vendor's platform but creates portability challenges.

Zephyr uses a device tree model borrowed from Linux. Hardware is described in .dts files, and drivers bind to device tree nodes through compatible strings. This provides hardware abstraction at the build system level — changing from an SPI temperature sensor to an I2C one requires modifying the device tree overlay, not application code. The ML inference pipeline benefits from this abstraction when deploying the same model across different sensor hardware.

/* Zephyr device tree overlay example */
&spi1 {
    bme280@0 {
        compatible = "bosch,bme280";
        reg = <0>;
        spi-max-frequency = <1000000>;
    };
};

/* Application code — hardware-agnostic */
const struct device *sensor = DEVICE_DT_GET_ONE(bosch_bme280);
sensor_sample_fetch(sensor);
sensor_channel_get(sensor, SENSOR_CHAN_AMBIENT_TEMP, &temp);

NuttX uses a character device model where drivers register as /dev/xxx entries. Applications interact through standard open(), read(), write(), and ioctl() calls. This is natural for developers with Unix experience but provides less type safety than Zephyr's sensor API.

Build System and Configuration

FreeRTOS is configured through a single FreeRTOSConfig.h header file with #define macros. This simplicity is both its strength (no build system to learn) and its limitation (no dependency resolution between features).

Zephyr uses Kconfig for feature selection and CMake for build management. The Kconfig system handles dependencies between subsystems — enabling Bluetooth automatically pulls in the required crypto libraries. The west meta-tool manages the multi-repository workspace, which can feel heavy for teams used to simpler setups but scales well for large projects with multiple external modules.

NuttX uses Kconfig (same tool as Zephyr and Linux) with Make or CMake. The make menuconfig interface will be familiar to Linux kernel developers. Board support packages follow a structured directory layout that maps closely to the Linux kernel's architecture.

Hardware Support and Community

DimensionFreeRTOSZephyrNuttX
Supported boards40+ official, vendor SDKs500+ in-tree200+ boards
Primary backerAWS / AmazonLinux FoundationApache Foundation
LicenseMITApache 2.0Apache 2.0
CI testingPer-vendorComprehensive in-treeGrowing CI coverage
Cloud integrationAWS IoT nativeMultiple (Azure, AWS, GCP)Manual integration
Safety certificationSAFERTOS variant (commercial)IEC 61508 work in progressNo formal certification

FreeRTOS has the largest installed base and the broadest silicon vendor support. Every major MCU vendor provides a FreeRTOS port as part of their SDK. Zephyr has the most active development community and the fastest-growing board support, with major contributions from Intel, Nordic, NXP, and ST. NuttX has a smaller but focused community, with strong contributions from Sony (used in their Spresense platform) and Samsung (Tizen RT).

Selection Criteria

The right RTOS depends on project constraints:

  • Choose FreeRTOS when you need the smallest footprint, when your silicon vendor's SDK is FreeRTOS-based, when integrating with AWS IoT services, or when your team is most productive with a minimal kernel they fully understand
  • Choose Zephyr when you need integrated Bluetooth/Thread/LoRaWAN, when portability across vendors matters, when you want comprehensive CI testing, or when building a product line that spans multiple hardware platforms
  • Choose NuttX when porting Linux applications to embedded hardware, when you need MPU-enforced task isolation, when your team has Unix/Linux systems programming expertise, or when building audio/multimedia applications (NuttX's audio framework is mature)
Selection Guide: Match Project Needs to RTOS Strengths FreeRTOS + Smallest footprint + Vendor SDK support + AWS IoT native - No integrated BLE/Thread - No device tree HAL Zephyr + Full protocol stack + Device tree portability + 500+ boards in CI - Steeper learning curve - Larger base footprint NuttX + POSIX compatibility + MPU task isolation + Linux code portability - Larger min footprint - Smaller community Evaluate against your project's specific constraints — no single RTOS is universally best

Frequently Asked Questions

Which RTOS has the smallest memory footprint?

FreeRTOS at approximately 6 KB flash and 1 KB RAM for a basic kernel. Zephyr starts at ~8 KB flash. NuttX requires ~32 KB flash for POSIX compatibility. However, when adding networking and security, Zephyr's integrated subsystems often produce a smaller total footprint than FreeRTOS with equivalent third-party libraries.

Is FreeRTOS or Zephyr better for IoT product development?

Zephyr is generally better for new IoT products due to integrated networking (BLE, Thread, LoRaWAN), device tree hardware abstraction, and comprehensive CI testing. FreeRTOS is better for smallest-footprint devices, AWS IoT integration, or when using a vendor SDK built on FreeRTOS.

Does NuttX provide full POSIX compliance?

NuttX provides the most complete POSIX implementation among embedded RTOSes — pthreads, file descriptors, sockets, signals, and VFS. It is not fully POSIX.1-2017 compliant, but covers enough that many Linux userspace programs compile with minimal modification.

Can I use multiple RTOSes in the same product line?

Yes — a constrained sensor might run FreeRTOS on a Cortex-M0+, while the gateway runs Zephyr on a Cortex-M33 with TrustZone. Using POSIX-compatible APIs and a hardware abstraction layer reduces porting effort across RTOS boundaries.

What are the real-time performance differences?

Interrupt latency is comparable (1-5 us on Cortex-M4). Context switch is fastest on FreeRTOS (2-4 us), then Zephyr (3-6 us), then NuttX (5-10 us). For most IoT applications these differences are negligible — they matter primarily in motor control and industrial control applications.

Related Articles

F

Fajar Nugroho

RTOS Platform Engineer

Technical analysis at TokoSport Bandung. Focuses on real-time operating systems and embedded platform architecture.