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)