Embedded Swift is a compiler mode designed to run the Swift language on microcontroller-class hardware, and it crossed a significant maturity threshold with Swift 6.4, released on September 15, 2026. This article covers the real boundaries of embedded Swift IoT firmware development as of October 2026, what Swift 6.4 actually changed, and the real architectural decisions you'll face when connecting an IoT device to your iOS app.
💡 Pro Tip: Embedded Swift isn't "a slimmed-down dialect of Swift" — it's a subset of full Swift. Code that compiles in Embedded mode also compiles in regular Swift; the reverse isn't always true.
Table of Contents
- What Embedded Swift Is, and What Constraints It Works Under
- Why this distinction matters
- The Embedded Foundation Laid in Swift 6.3
- Toolchain Setup and Your First Firmware
- Memory and Binary Budget: What We Actually Know
- The Embedded Improvements That Landed in Swift 6.4
- IoT Device + iOS Pairing Architecture
- Is It Production-Ready? (October 2026)
- FAQ
- What hardware can Embedded Swift be used on?
- What are the constraints between Embedded Swift and regular Swift?
- What did Swift 6.4 bring on the embedded side?
- How do you connect Embedded Swift firmware to an iOS app?
- Which Swift version should I start my Embedded Swift project with?
- Conclusion
- Sources
What Embedded Swift Is, and What Constraints It Works Under
The official framing of Embedded Swift was laid out in the "A Vision for Embedded Swift" document in the swift-evolution repository; in the document's own words, the motivation is "to achieve a first class support for embedded platforms and unblock porting and using Swift in small environments." The official positioning is clear: features specific to desktop/server Swift, such as runtime reflection (Mirror APIs) and ABI stability, are disabled, while the rest of the language stays largely the same.
Before Swift 6.4, one of the most concrete constraints was existential types: only protocols constrained with AnyObject could be used as any. Swift 6.4 changed this — now all any types, including Any, are supported in Embedded Swift. That said, calling a generic function directly on an any P value is still not possible; the compiler emits "cannot use generic instance method ... on a value of type 'any P' in Embedded Swift." In other words, you can carry existentials around, but you still need concrete types for generic dispatch.
There's also a hardware distinction, and skipping it is a common mistake: Embedded Swift has official example projects on many ARM Cortex-M and RISC-V microcontrollers — the STM32F746G-DISCO, Raspberry Pi Pico / Pico 2 / Pico W, Nordic nRF52840-DK, and Espressif's RISC-V-based ESP32-C6 (esp32-led-blink-sdk, esp32-led-strip-sdk, esp32-uart-echo) each have their own project in the official example repository. The docs deliberately limit the claim: "Embedded Swift is not a complete one-click solution to program all embedded boards and MCUs" — the linker script, flash format, and flashing tool still come from the vendor's own toolchain. The classic Xtensa ESP32 / ESP32-S2 / ESP32-S3 aren't on this list; per the relevant Swift Forums thread, "newer MCUs are based on RISC-V and are supported by the upstream compiler, those using Xtensa require a custom compiler build." Saying "Embedded Swift runs on ESP32" can be right or entirely wrong depending on which variant you mean.
Why this distinction matters
If you're choosing hardware for an IoT firmware project based on Embedded Swift support, you need to confirm the architecture before locking down the product spec. For example, while the ESP32-C6 is RISC-V-based, the classic ESP32 (Xtensa LX6) — still the most common reference hardware in the developer community — falls outside this list and requires a custom compiler build.
The Embedded Foundation Laid in Swift 6.3
Swift 6.3 was released on March 24, 2026, and announced improvements for embedded environments as one of its headline items. Two features that shipped with this release directly affect IoT firmware + host application (a CLI written in Swift, a server component, or a C-based SDK) integration:
- The
@cattribute: lets you expose Swift functions and enums to C code — useful for injecting a Swift function into an existing C-based firmware/HAL layer. - Module selector (
::): lets you specify which module Swift should search when multiple imported modules share the same name — useful for resolving name collisions in a growing embedded project tree.
Toolchain Setup and Your First Firmware
The most realistic way to get started with Embedded Swift is to match one of the targets in the official swift-embedded-examples repository to your own hardware. The repository covers ESP32 (via ESP-IDF), the nRF52840-DK (Zephyr), the Raspberry Pi Pico W (a Bluetooth speaker example with Harmony), and RISC-V targets on QEMU/NuttX. On the STM32 side, the swift.org/get-started/embedded page recommends a fully bare-metal path (no operating system) using Swift MMIO.
There are two ways to enable Embedded mode in a Swift package: pass the flags to the target with swiftSettings in Package.swift, or collect them in a toolset JSON file the way the official examples do — you don't need to use both. The first way looks like this:
1// Package.swift — compiler flags for the embedded target2let package = Package(3 name: "BlinkFirmware",4 targets: [5 .executableTarget(6 name: "BlinkFirmware",7 swiftSettings: [8 .enableExperimentalFeature("Embedded"),9 .unsafeFlags(["-wmo"]) // whole-module optimization is required10 ]11 )12 ]13)Whole-module optimization (-wmo) is required: in embedded mode the compiler errors out outright without wmo. Whole-module compilation also lets it strip out most of the runtime metadata at compile time.
The safest way to write your first firmware entry point is to copy it from the official example: the bare-metal stm32-blink example in the swift-embedded-examples repository uses the @main struct Application form. @_cdecl is a different scenario — it's useful for providing the entry function a C-side SDK expects (e.g., ESP-IDF's app_main) from Swift:
1// Application.swift — blinks the LED on pin I1 on an STM32F746G-DISCO board2// (structure taken from the swift-embedded-examples/stm32-blink example)3import STM32F7X64import Support5 6@main7struct Application {8 static func main() {9 // Enable the AHB1 clock for GPIO port I10 rcc.ahb1enr.modify { $0.raw.gpioien = 1 }11 12 // Configure pin I1 as push-pull, low-speed, pull-down output13 gpioi.moder.modify { $0.raw.moder1 = 0b1 }14 gpioi.otyper.modify { $0.raw.ot1 = 0b0 }15 gpioi.ospeedr.modify { $0.raw.ospeedr1 = 0b00 }16 gpioi.pupdr.modify { $0.raw.pupdr1 = 0b10 }17 18 var enable = false19 while true {20 gpioi.odr.modify { $0.raw.odr1 = enable ? 1 : 0 }21 enable.toggle()22 delay(milliseconds: 100)23 }24 }25}26 27func delay(milliseconds: Int) {28 for _ in 0..<10_000 * milliseconds { nop() }29}The build command depends on the target architecture (triple), and on bare-metal targets it won't work without a toolset/SDK definition. Here's the line the official stm32-blink Makefile uses:
1# The build invocation used in swift-embedded-examples/stm32-blink/Makefile2swift build \3 --build-system native \4 --configuration release \5 --triple armv7em-apple-none-macho \6 --toolset Tools/Toolsets/stm32f74x.jsonIf you want to work directly with the compiler without SwiftPM, the canonical form on the official "Learning the basics of Embedded Swift" page is swiftc -target <target triple> -enable-experimental-feature Embedded -wmo input1.swift ... -c -o output.o; the target triple also determines whether the output is ELF or Mach-O. The actual pin map and linker script for your target hardware must always be taken from the hardware vendor's reference documentation (e.g., STMicroelectronics, Nordic, Raspberry Pi Foundation).
Memory and Binary Budget: What We Actually Know
Embedded Swift's official positioning sets a clear goal: "producing meaningful programs measured in kilobytes" (swift.org/get-started/embedded). The mechanism that makes this possible is the complete removal of runtime reflection, monomorphizing generics at compile time wherever possible, and mandating whole-module optimization — together, these three disable the parts of the typical Swift runtime that take up the most space on microcontrollers.
There are three concrete figures in the official sources that give a sense of scale. The swift.org/get-started/embedded page says, for the Conway's Game of Life app on the Playdate handheld, "In just 788 bytes of resulting compiled code." The Embedded Swift documentation's landing page describes the general scale as "Small binaries that can be as tiny as a few hundred bytes for 'Hello World'-like programs (fully self-contained)" and states the runtime library "is itself less than a kilobyte in size, and is eligible to be removed if unused."
It's worth being honest here: these numbers are order-of-magnitude indicators — there's no official per-target budget table published; the actual budget is a variable that depends on the target architecture you choose, the library surface you use (e.g., whether you include the concurrency library), and the compiler optimization level. The only reliable way to get a real number for your own project is to measure your own compiled binary with arm-none-eabi-size (or the appropriate size tool for your target) and track it commit by commit — one-off "it fit in X KB" anecdotes floating around online shouldn't be carried into project planning without their hardware/library context.
The Embedded Improvements That Landed in Swift 6.4
On August 20, 2026, Swift Language Steering Group member Doug Gregor announced, in a post titled "Embedded Swift Improvements Coming in Swift 6.4," a set of improvements that could at the time be tested in development snapshots. Swift 6.4 was officially released on September 15, 2026 (in the words of the Xcode 27 release notes, "Xcode 27 includes Swift 6.4"), and these improvements are no longer a development preview — they're now part of the stable release:
- All
anyexistential types are supported — previously only protocols constrained byAnyObjectcould be used; now all existentials, includingAny, are valid in Embedded Swift. - Full support for metatypes — including existential metatypes.
- Full support for "untyped throws" — error handling is now closer to desktop Swift.
- String → Double parsing APIs have been brought to Embedded Swift.
- The concurrency library supports throwing tasks/task groups — error propagation in async firmware code is now possible.
All of these items turn scenarios in IoT firmware that previously required a workaround (e.g., using real throws instead of an error code, carrying multiple protocols in a single any variable) into directly supported ones.
To put it concretely: in 6.3, writing a sensor abstraction, you'd run into the AnyObject constraint; in 6.4 you can carry the same protocol as an existential with non-class types too:
1// Before Swift 6.4: only AnyObject-constrained protocols could be "any"2protocol SensorReading: AnyObject {3 var celsius: Double { get }4}5 6// Swift 6.4: a struct-based protocol can now also be carried as "any"7protocol SensorReading {8 var celsius: Double { get }9}10 11struct TemperatureSample: SensorReading {12 let celsius: Double13}14 15func logReading(_ reading: any SensorReading) {16 // Compiles on Embedded Swift 6.4; on 6.3, using "any" for17 // struct-based protocols was not supported.18 print(reading.celsius)19}The boundary still stands: if you try to call a generic method on reading from inside logReading (e.g., a generic map), the compiler redirects you back to a concrete type — carrying an existential is free, but generic dispatch still requires static resolution.
IoT Device + iOS Pairing Architecture
Let's be clear here: swift.org's official Embedded Swift resources do not publish an official "pairing architecture" document that connects a microcontroller firmware to an iOS companion app — the Embedded Swift documentation focuses on the hardware side, the iOS SDK documentation focuses on the host side, and there's no official guide that unifies the two. In practice, this means you have to build the bridge between the two sides yourself, within your own architecture.
In practice, the most mature bridge works over Bluetooth Low Energy (BLE): the firmware publishes GATT services, while iOS connects with Core Bluetooth and manages the data exchange. We covered which GATT characteristics to define and how to recover from connection drops on the iOS side, building this end to end, in our Core Bluetooth and BLE guide. You can see how this bridge combines with an offline-first sync layer in a real production case in the ESP-Point case study — the firmware there isn't written in Swift, but the patterns (connection drops, queuing, conflict resolution) apply directly to Embedded Swift firmware too.
The table below summarizes three capabilities that changed in Embedded Swift between Swift 6.3 and 6.4 — useful for seeing which workarounds you can remove as you migrate your firmware codebase to 6.4:
Capability | Swift 6.3 | Swift 6.4 |
|---|---|---|
any existential types | Only AnyObject-constrained protocols | All any types (including Any) |
Metatype support | Partial | Full (including existential metatypes) |
Error handling | Typed throws | Untyped throws now fully supported |
Concurrency + throws | Task/TaskGroup not throwing | Task/TaskGroup throwing supported |
Is It Production-Ready? (October 2026)
Two official sources say different things here. The docs still describe Embedded Swift as experimental: the docs.swift.org/embedded page says "Embedded Swift is experimental. Public releases of Swift do not support Embedded Swift, yet," and the install page says "Since Embedded Swift is still experimental and not yet supported in public Swift releases, you'll need to use a development toolchain," recommending swiftly install main-snapshot. The Swift 6.4 announcement, though, lists embedded improvements as part of the release: "Embedded Swift grows more capable, with support for existential types and richer error handling for microcontroller-class targets." So the language capabilities ship with the release notes, but the install path still points to a snapshot toolchain — rather than a flat yes/no on "production-ready," it's more accurate to decide knowing the concrete boundaries.
A realistic take based on Swift 6.4: language-level constraints have largely lifted (existentials, metatypes, throws), hardware support is clear and expanding (ARM Cortex-M + RISC-V), but two things are still on you — (1) getting the Xtensa/RISC-V distinction right, and (2) building the iOS companion bridge yourself, since there's no official template. It's realistic for small-to-medium sensor/actuator firmware; for a safety-critical system (medical, automotive), separately evaluate the current certification/tooling maturity — there's no official certification statement here.
You can use the matrix below as a reference for narrowing down your hardware choice — targets exemplified in the official swift-embedded-examples repository:
Hardware | Architecture | Support status |
|---|---|---|
STM32F746G-DISCO | ARM Cortex-M7 | Bare-metal + Swift MMIO example exists |
Raspberry Pi Pico / Pico W | ARM Cortex-M0+ | Pico SDK and Harmony examples exist |
Nordic nRF52840-DK | ARM Cortex-M4 | Zephyr SDK example exists |
ESP32-C6 | RISC-V | Three official examples via ESP-IDF SDK |
ESP32 / ESP32-S2 / ESP32-S3 | Xtensa | Not in upstream compiler; custom build |
GOLDEN TIP
The most valuable insight in this article
This tip holds the article's most important takeaway.
Easter Egg
You found a hidden gem!
There's a hidden detail in this section. Want to uncover it?
Reader Reward
We put together a checklist of the steps you shouldn't skip when starting an IoT firmware project with Embedded Swift. If you complete this list on day one of your project, you'll avoid the cost of changing architecture later.
FAQ
What hardware can Embedded Swift be used on?
Embedded Swift runs on many microcontrollers with ARM Cortex-M and RISC-V architectures; the STM32F746G-DISCO, Raspberry Pi Pico / Pico 2 / Pico W, Nordic nRF52840-DK, and Espressif's RISC-V-based ESP32-C6 all have their own projects in the official example repository. That said, the official documentation says "Embedded Swift is not a complete one-click solution to program all embedded boards and MCUs": you'll need the hardware vendor's toolchain for the linker, flash format, and flashing tool. One important exception: the classic Xtensa-architecture ESP32/ESP32-S2/S3 are not supported in the upstream compiler and require a custom compiler build — skipping this distinction is a common mistake.
What are the constraints between Embedded Swift and regular Swift?
Embedded Swift was designed to be a subset of full Swift: features like runtime reflection (Mirror APIs) and ABI stability are disabled. Before Swift 6.4, broad use of any/existentials was also restricted, but that changed with 6.4 — now all existential types, including Any, and metatypes are supported. The general principle still holds: code that compiles in Embedded mode also compiles in regular Swift; the reverse isn't always true.
What did Swift 6.4 bring on the embedded side?
Swift 6.4 was released on September 15, 2026, and brought three concrete gains to Embedded Swift: (1) support for all existential/any types without the AnyObject constraint, (2) full support for metatypes, including existential metatypes, and (3) richer error handling for microcontroller-class targets, including untyped throws and throwing concurrency.
How do you connect Embedded Swift firmware to an iOS app?
The most mature approach is GATT services over Bluetooth Low Energy: the firmware side publishes the services, and the iOS side connects with Core Bluetooth to read/write the data. Since there's no official "pairing architecture" document, you need to design this bridge to fit your own project's requirements.
Which Swift version should I start my Embedded Swift project with?
Swift 6.4 was released on September 15, 2026, and lists embedded existential/metatype improvements as part of the release, so there's no reason to fall back to the 6.3 baseline for a new project. That said, the official setup guide still says "you'll need to use a development toolchain" for Embedded Swift and recommends installing a development snapshot with swiftly install main-snapshot — plan your toolchain accordingly.
Conclusion
Embedded Swift has matured from its vision-document goal to today, across two major releases (6.3, 6.4) as of September 2026, and now brings desktop-Swift features like existential types, metatypes, and throwing concurrency to microcontroller-class hardware. Hardware support is clear: ARM Cortex-M and RISC-V are strong, while the classic Xtensa ESP32 variants are left out; the docs still call the mode experimental and recommend a development snapshot toolchain. If your next step is connecting your firmware to an iOS app, our Core Bluetooth and BLE guide is a practical start; for a real offline-first sync architecture, see the ESP-Point case study.
For async firmware code on the Swift side, we cover TaskGroup and AsyncStream patterns in our Swift Structured Concurrency guide; for actor isolation warnings during Swift 6's strict concurrency migration, see our Swift 6.3 migration guide. As your firmware and host app grow, our advanced Swift Package Manager guide covers splitting into modules, and for offline scenarios on iOS, our iOS Offline-First Architecture article is a complementary resource.
Sources
- Swift 6.4 Released — the official release announcement for Swift 6.4, dated September 15, 2026.
- Embedded Swift Improvements Coming in Swift 6.4 — the first announcement of the existential, metatype, and throws improvements, August 20, 2026.
- Swift 6.3 Released — the 6.3 announcement, including the
@cattribute, module selector, and embedded improvements. - Get Started with Embedded Swift — the official introductory page, including the 788-byte Game of Life example on the Playdate.
- Embedded Swift Documentation — the official documentation; the "Embedded Swift is experimental" note and the binary/runtime size statements are here.
- Installing Embedded Swift — installing the development snapshot toolchain with swiftly.
- Learning the basics of Embedded Swift — the canonical
swiftc -target ... -enable-experimental-feature Embedded -wmobuild form. - A Vision for Embedded Swift — the official vision document defining Embedded Swift's goals and approach.
- Embedded Swift support for ESP32-S3, ESP32-S2 and original ESP32 (Xtensa arch) — a Swift Forums thread explaining that Xtensa variants require a custom compiler build.
- swift-embedded-examples (GitHub) — example projects for ESP32, nRF52840, Raspberry Pi Pico, and QEMU/NuttX.
- Xcode 27 Release Notes — the official source for "Xcode 27 includes Swift 6.4."
Tags
iOS Development News
Weekly Swift tips, SwiftUI tricks and iOS best practices. No spam, only valuable content.
Your subscription starts when you open the link in the confirmation email and press “Confirm my subscription”. The newsletter keeps open/click statistics; you can unsubscribe anytime with one click. Privacy

