DEV Community

Cover image for TinyGo Magic: Build Lightning-Fast IoT Apps with Only 512KB RAM!
Yevhen Kozachenko ๐Ÿ‡บ๐Ÿ‡ฆ๐Ÿ‡ฉ๐Ÿ‡ช
Yevhen Kozachenko ๐Ÿ‡บ๐Ÿ‡ฆ๐Ÿ‡ฉ๐Ÿ‡ช

Posted on Originally published at ekwoster.dev

TinyGo Magic: Build Lightning-Fast IoT Apps with Only 512KB RAM!

TinyGo Magic: Build Lightning-Fast IoT Apps with Only 512KB RAM!

Ever dreamt of creating microcontroller-based web-enabled applications without writing a single line of C? What if I told you that you could run Go (yes, the Go language!) on an Arduino-class device with less than 1MB of RAM and still have room to run WASM code too?! This isnโ€™t science fictionโ€”welcome to the world of TinyGo.

In this blog post, weโ€™ll dive into something different: building an ultra-lightweight HTTP sensor logger using TinyGo on a low-power microcontroller and a WebAssembly dashboardโ€”all running blazingly fast with minimal overhead.


โšก๏ธ Why TinyGo?

Go is a powerful programming language, but its runtime usually requires megabytes of memory. TinyGo is a compiler for Go that targets microcontrollers and WebAssembly:

  • Compiles Go code to run on chips like the Arduino Nano 33 IoT or Raspberry Pi Pico
  • Strips down the Go runtime to fit into the tiniest of memory footprints
  • Makes it possible to write maintainable, concurrent-friendly, and type-safe applications for embedded systems

But here's the twist: TinyGo can also compile to WebAssembly (WASM), so we can share code between microcontrollers and the front-end. ๐Ÿ’ฅ


๐Ÿ›  Project Breakdown: IoT Sensor Logger with WASM GUI

Here's what we're building:

  • A microcontroller (say, a Nano 33 IoT) that reads temperature data and serves it via HTTP
  • The controller runs firmware compiled with TinyGo
  • A frontend dashboard runs in a web browser using a WASM module also built with TinyGo
  • No C/C++, no NodeJS, just Go for everything

We'll explore all of it with code! Letโ€™s roll ๐Ÿš€


๐Ÿง  Step 1: Firmware in TinyGo

Install TinyGo first:

$ brew tap tinygo-org/tools
$ brew install tinygo
Enter fullscreen mode Exit fullscreen mode

Create the firmware code (firmware.go):

package main

import (
    "machine"
    "time"
    "tinygo.org/x/drivers/dht"
)

var sensor dht.Device

func main() {
    sensor = dht.New(machine.D2, dht.DHT22)
    for {
        temp, _, err := sensor.ReadTemperatureHumidity()
        if err == nil {
            println("Temperature:", temp)
            // You could publish via HTTP or MQTT
        }
        time.Sleep(2 * time.Second)
    }
}
Enter fullscreen mode Exit fullscreen mode

Then compile:

tinygo flash -target=arduino-nano33 firmware.go
Enter fullscreen mode Exit fullscreen mode

๐Ÿšจ Note: The TinyGo project supports dozens of MCUs. Youโ€™ll need to check your board compatibility: TinyGo targets.


๐ŸŒ Step 2: Embedded HTTP Server (TinyGo + RTOS)

TinyGo doesnโ€™t yet support built-in HTTP on microcontrollers, so we emulate a basic REST server using serial output or use MQTT via a helper runtime (like ESP32 + FreeRTOS via CGo interface). For demonstration, letโ€™s mock a serial-fed JSON output and use a USB serial reader on the dashboard end.

Or, better yet, let's redirect the data via serial to a Go-powered bridge on your local machine:

// bridge.go
package main

import (
    "bufio"
    "fmt"
    "net/http"
    "os"
    "strings"
)

var latestTemp string

func main() {
    // read from serial (emulated)
    go func() {
        serial := bufio.NewReader(os.Stdin)
        for {
            line, _ := serial.ReadString('\n')
            if strings.HasPrefix(line, "Temperature:") {
                latestTemp = strings.TrimSpace(line)
            }
        }
    }()

    // Serve HTTP
    http.HandleFunc("/temp", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, `{"temperature": "%s"}`, latestTemp)
    })

    http.ListenAndServe(":8080", nil)
}
Enter fullscreen mode Exit fullscreen mode

๐Ÿงฑ Step 3: Frontend with WASM + TinyGo

Go WebAssembly is powerful, but with TinyGo, itโ€™s even leaner. First, install wasm_exec.js from TinyGo:

cp $(tinygo env TINYGOROOT)/targets/wasm_exec.js ./
Enter fullscreen mode Exit fullscreen mode

Create a frontend Go file:

// dashboard.go
package main

import (
    "syscall/js"
    "time"
)

func fetchTemp(this js.Value, p []js.Value) interface{} {
    go func() {
        res, err := js.Global().Get("fetch").Invoke("http://localhost:8080/temp")
        if err == nil {
            js.Global().Call("console", res)
        }
    }()
    return nil
}

func main() {
    js.Global().Set("fetchTemp", js.FuncOf(fetchTemp))
    select {} // prevent exit
}
Enter fullscreen mode Exit fullscreen mode

Build it:

tinygo build -o main.wasm -target wasm dashboard.go
Enter fullscreen mode Exit fullscreen mode

Hook up a simple HTML file:

<!DOCTYPE html>
<html>
  <head>
    <title>TinyGo WASM Dashboard</title>
    <script src="wasm_exec.js"></script>
    <script>
      const go = new Go();
      WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject).then((result) => {
        go.run(result.instance);
      });
      setInterval(() => fetchTemp(), 2000);
    </script>
  </head>
  <body>
    <h1>Checking temperature...</h1>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

๐Ÿš€ What Did We Just Do?

  • Built MCU firmware with a modern language โŒ C not needed
  • Interfaced sensors using Go with rich type system
  • Created a bridge server to expose MCU data to the web
  • Developed a frontend client with shared Go code compiled to WASM

๐Ÿง  Why This Matters

  • TinyGo is perfect for education: reduce complexity, increase clarity
  • Safe, garbage-collected, concurrent IoT firmware
  • Write once, deploy on both device + browser
  • Ideal for maker projects, low-power deployments, and sensor data loggers

๐Ÿ Final Thoughts

Thereโ€™s a learning curve, sureโ€”but TinyGo opens up a future where even the tiniest devices get smart without bloated stacks.

If you want to go further:

  • Add MQTT support via C bindings
  • Build a UI with Svelte + WASM modules
  • Store data in Supabase or Mongo

Let me know if youโ€™d like that in the next post ๐Ÿ˜Ž.

"Your microcontroller deserves more than just C. Let Go handle it." ๐Ÿฆพ


๐Ÿ‘‰ If you're building resource-constrained systems or exploring embedded WASM, we offer research and development services to bring your ideas to life.

Top comments (0)