Back

WebAssembly além do navegador: WASI 2.0, Component Model e por que Wasm vai mudar tudo

Pra maioria dos devs web, WebAssembly significa uma coisa: fazer cálculo pesado rodar mais rápido no navegador. Você provavelmente já viu no Figma, no Photoshop web ou naquele editor de vídeo que funciona inteiro numa aba. Legal, mas nicho.

Agora, tem uma coisa que talvez você não percebeu: WebAssembly tá virando um runtime universal. Não só pra browser — pra servidor, funções no edge, dispositivo IoT, e até como alternativa a containers Docker em certos cenários.

WASI 0.3.0 acabou de sair. O Component Model tá se estabilizando. Cloudflare Workers, Fastly Compute e Fermyon Cloud rodam Wasm em produção em escala. Docker tem suporte nativo pra Wasm. E o ferramental finalmente ficou utilizável de verdade.

Não é conversa de futuro. Tá acontecendo agora, e rápido.


Peraí, o que é WASI?

Versão curta

WASI (WebAssembly System Interface) permite que módulos Wasm acessem recursos do sistema — arquivos, rede, relógio, números aleatórios — de forma segura e portável. Pensa como o POSIX do Wasm.

Por que isso importa

Sem WASI, WebAssembly só faz computação pura. Consegue processar números, mas não lê um arquivo, não faz request HTTP, não pega nem a hora atual. No browser, onde o JavaScript cuida de todo o I/O, tudo bem. Mas no servidor, assim não dá pra fazer nada.

WASI resolve isso com interfaces padronizadas:

Sem WASI:                       Com WASI:
┌──────────────┐               ┌──────────────┐
│  Módulo Wasm │               │  Módulo Wasm │
│              │               │              │
│  Só cálculo  │               │  Arquivos    │
│  puro        │               │  Rede        │
│              │               │  Timers      │
│  Sem I/O     │               │  Variáveis   │
│  Sem arquivo │               │  HTTP        │
└──────────────┘               └──────────────┘

O modelo de segurança: aqui fica bom

Aqui que o WASI brilha. Processo normal do SO tem acesso a tudo por padrão, certo? WASI é ao contrário: o módulo Wasm só acessa o que você autorizar explicitamente:

# Rodando um módulo Wasm com wasmtime # Este módulo SÓ pode ler de /data e escrever em /output wasmtime run --dir /data::readonly --dir /output myapp.wasm # Ele não pode: # ❌ Acessar /etc/passwd # ❌ Fazer requests de rede (sem --tcplisten) # ❌ Ler variáveis de ambiente (sem --env) # ❌ Acessar nenhum outro diretório

Compara com um container Docker, que por padrão tem acesso a todo o seu filesystem. WASI vem trancado de fábrica. Segurança não é configuração, é o default.


WASI 0.3.0: o que mudou

I/O assíncrono

A maior novidade. Versões anteriores do WASI só tinham I/O bloqueante — o módulo não conseguia lidar com várias operações ao mesmo tempo. WASI 0.3.0 traz o modelo de futures e streams:

// WASI 0.3.0 - handler HTTP assíncrono use wasi::http::incoming_handler; use wasi::io::streams; async fn handle_request(request: IncomingRequest) -> OutgoingResponse { // Leitura de arquivo não-bloqueante let data = streams::read("config.json").await?; // Chamada HTTP não-bloqueante let api_response = wasi::http::outgoing_handler::handle( OutgoingRequest::new("https://api.example.com/data") ).await?; // Construir resposta OutgoingResponse::new(200, api_response.body()) }

Sem isso, não tinha por quê usar Wasm no servidor. Agora dá pra brigar de igual com Node.js e Go.

Interfaces estabilizadas

InterfaceFuncionalidadeStatus
wasi:filesystemLeitura/escrita de arquivosEstável
wasi:socketsNetworking TCP/UDPEstável
wasi:httpCliente e servidor HTTPEstável
wasi:clocksRelógio e timersEstável
wasi:randomAleatoriedade criptográficaEstável
wasi:cliArgumentos, env vars, stdioEstável
wasi:ioStreams e futures assíncronosNovo no 0.3

O que ainda falta (sendo honesto)

  • Acesso a GPU: Nenhuma interface GPU padronizada. Treinar IA ou processar gráficos pesados ainda não rola.
  • Threading: Proposta de threads existe mas não tá no 0.3.0. Tem concorrência assíncrona, mas paralelismo real ainda não.
  • Acesso ao DOM: WASI é pra fora do browser. Wasm no browser continua falando com o DOM via JavaScript.

Component Model: é aqui que o jogo muda de verdade

WASI dá capacidade de I/O pro Wasm. O Component Model dá composabilidade. E aí que a coisa fica séria.

A dor que todo mundo sente

Quer usar uma lib de processamento de imagem escrita em Rust numa aplicação Go? Hoje suas opções são:

  1. Reescrever em Go (trabalhão)
  2. Usar CGo com bindings C (sofrimento)
  3. Chamar como serviço separado por HTTP (lento, complexo)

O Component Model adiciona uma quarta opção: compilar ambos pra componentes Wasm e linkar diretamente. Compartilham memória, chamam funções um do outro, rodam no mesmo processo. Não importa a linguagem.

Abordagem tradicional:
┌──────────┐    HTTP     ┌──────────┐
│  App Go  │ ←────────→ │ Serviço  │
│          │   rede      │ Rust     │
└──────────┘  overhead   └──────────┘

Component Model:
┌────────────────────────────────┐
│  Componente Wasm composto      │
│  ┌──────────┐  ┌──────────┐  │
│  │  Go      │←→│  Rust    │  │
│  │  lógica  │  │  lib     │  │
│  └──────────┘  └──────────┘  │
│  Chamadas diretas de funções   │
│  Memória compartilhada, zero overhead│
└────────────────────────────────┘

WIT: a linguagem de interfaces

Componentes se comunicam através de definições WIT (Wasm Interface Type). Pensa em protobuf, mas pra componentes Wasm:

// image-processor.wit package mycompany:[email protected]; interface process { record image { width: u32, height: u32, data: list<u8>, } record options { quality: u8, format: string, } resize: func(img: image, target-width: u32, target-height: u32) -> image; compress: func(img: image, opts: options) -> list<u8>; detect-faces: func(img: image) -> list<bounding-box>; record bounding-box { x: u32, y: u32, width: u32, height: u32, } } world image-service { export process; }

Define o WIT uma vez, e daí:

  • Implementa em Rust, Go, Python, JavaScript, C/C++, ou C#
  • Consome de qualquer uma dessas linguagens
  • Sem FFI, sem serialização, sem código de cola

Vamos construir um componente

Criar um componente em Rust e usar em JavaScript:

Passo 1: Definir a interface

// greeter.wit package example:[email protected]; interface greet { greet: func(name: string) -> string; } world greeter { export greet; }

Passo 2: Implementar em Rust

// src/lib.rs wit_bindgen::generate!("greeter"); struct MyGreeter; impl Guest for MyGreeter { fn greet(name: String) -> String { format!("Hello, {}! Welcome to the Component Model.", name) } } export!(MyGreeter);
# Cargo.toml [package] name = "greeter" version = "0.1.0" edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] wit-bindgen = "0.36"

Passo 3: Compilar o componente

# Compilar o módulo Wasm cargo build --target wasm32-wasip2 --release # O target wasm32-wasip2 já gera um componente diretamente # target/wasm32-wasip2/release/greeter.wasm

Passo 4: Usar no JavaScript (com jco)

# Instalar jco (JavaScript Component Tools) npm install -g @bytecodealliance/jco # Converter o componente Wasm pra módulo importável no JS jco transpile greeter.wasm -o greeter-js/
// app.js import { greet } from './greeter-js/greeter.js'; console.log(greet("World")); // "Hello, World! Welcome to the Component Model."

Uma função Rust chamada direto do JavaScript. Serialização zero, HTTP zero, type-safe.


Quem tá usando Wasm em produção (de verdade)

1. Edge computing: Cloudflare Workers e Fastly Compute

O caso de uso mais maduro. Tanto o Cloudflare Workers quanto o Fastly Compute executam Wasm nativamente:

// Cloudflare Worker usando Wasm // Computação pesada no Wasm, roteamento no JS import { process_image } from './image-processor.wasm'; export default { async fetch(request) { const imageData = await request.arrayBuffer(); // Roda com velocidade quase nativa const result = process_image( new Uint8Array(imageData), 800, // largura alvo 600 // altura alvo ); return new Response(result, { headers: { 'Content-Type': 'image/webp' }, }); }, };

Por que Wasm no edge:

  • Cold start: Containers levam centenas de ms → Wasm leva microssegundos
  • Memória: Node.js ~50-200MB → Wasm 1-10MB
  • Segurança: Sandbox por padrão, escape de container impossível
  • Portabilidade: O mesmo binário roda em x86, ARM, RISC-V

2. Sistemas de plugins: extensões seguras

Um caso de uso que tá crescendo rápido. Rodar plugins de terceiros no mesmo processo é um risco de segurança; em containers separados é lento. Rodar como componentes Wasm resolve ambos:

Arquitetura de plugins tradicional:
┌─────────────────────────┐
│  Aplicação Host          │
│  ┌───────────────────┐  │
│  │  Plugin (JS/Lua)  │  │  ← Acesso total à memória do host
│  │  Pode crashear    │  │  ← Acesso ao filesystem do host
│  │  Memory leaks     │  │  ← Syscalls arbitrários
│  └───────────────────┘  │
└─────────────────────────┘

Arquitetura de plugins Wasm:
┌─────────────────────────┐
│  Aplicação Host          │
│  ┌───────────────────┐  │
│  │  Plugin (Wasm)    │  │  ← Sandbox de memória isolado
│  │  Não crasheia     │  │  ← Só capabilities autorizadas
│  │  Memory-safe      │  │  ← Uso de recursos determinístico
│  └───────────────────┘  │
└─────────────────────────┘

Exemplos reais:

  • Envoy Proxy: plugins Wasm pra roteamento e filtragem customizados
  • Shopify Functions: lógica de merchants roda como Wasm
  • Figma: plugins rodam em sandbox Wasm
  • Zed Editor: extensões são componentes Wasm
  • Extism: framework pra sistemas de plugins baseados em Wasm

3. Docker + Wasm: alternativa a containers

Docker adicionou suporte nativo pra Wasm a partir do Docker Desktop 4.15+. Dá pra rodar containers Wasm junto com containers Linux tradicionais:

# Dockerfile tradicional FROM node:20-slim WORKDIR /app COPY . . RUN npm install CMD ["node", "server.js"] # Tamanho da imagem: ~200MB # Cold start: ~500ms
# "Dockerfile" Wasm (base wasm/wasi) FROM scratch COPY myapp.wasm /myapp.wasm ENTRYPOINT ["/myapp.wasm"] # Tamanho da imagem: ~2MB # Cold start: ~1ms
# Rodar um container Wasm docker run --runtime=io.containerd.wasmtime.v2 \ --platform wasi/wasm \ myregistry/myapp:latest

Quando usar containers Wasm:

  • ✅ Endpoints de API sem estado
  • ✅ Pipelines de processamento de dados
  • ✅ Ferramentas CLI e utilitários
  • ✅ Funções que precisam de cold start rápido
  • ❌ Apps que precisam de GPU
  • ❌ Serviços stateful de longa duração
  • ❌ Apps com muitas dependências de SO

4. Inferência de IA no edge

Rodar modelos ML leves em Wasm já é viável:

// Inferência ONNX em Wasm use wasi_nn::{Graph, GraphEncoding, ExecutionTarget, Tensor}; fn classify_image(image_data: &[u8]) -> Vec<f32> { // Carregar o modelo ONNX let graph = Graph::load( &[model_bytes], GraphEncoding::Onnx, ExecutionTarget::Cpu, ).unwrap(); let context = graph.init_execution_context().unwrap(); // Configurar tensor de entrada context.set_input(0, Tensor::new( &[1, 3, 224, 224], // batch, channels, height, width TensorType::F32, image_data, )).unwrap(); // Executar inferência context.compute().unwrap(); // Pegar saída context.get_output(0).unwrap() }

Especialmente interessante pra IA no edge: o mesmo binário Wasm funciona no Cloudflare Workers, no browser e num dispositivo IoT.


Performance: menos papo, mais número

Tempo de arranque

Comparação de cold start (handler HTTP simples):
┌──────────────────────────────────────────────┐
│  Docker (Node.js):    ~500ms                 │
│  Docker (Go):         ~100ms                 │
│  AWS Lambda (Node):   ~200ms                 │
│  Wasm (Wasmtime):       ~1ms                 │
│  Wasm (Spin):           ~1ms                 │
└──────────────────────────────────────────────┘

Essa melhora de 100-500x é por que plataformas serverless adoram Wasm. Em workloads scale-to-zero, tempo de arranque impacta diretamente a latência.

Throughput

Pra trabalho CPU-bound, Wasm atinge 80-95% da velocidade nativa. A diferença diminuiu bastante:

Benchmark de JSON parsing (1MB payload):
┌──────────────────────────────────────────────┐
│  Rust nativo:         12.3ms                 │
│  Wasm (Wasmtime):     14.1ms  (87% do nativo)│
│  Node.js:             28.7ms                 │
│  Python:              89.4ms                 │
└──────────────────────────────────────────────┘

Memória

Footprint de memória (servidor HTTP idle):
┌──────────────────────────────────────────────┐
│  Node.js:              ~50MB                 │
│  Go:                   ~15MB                 │
│  Wasm (Spin):           ~2MB                 │
└──────────────────────────────────────────────┘

Onde Wasm NÃO é mais rápido

Sendo honesto sobre as limitações:

  • Workloads com muito I/O: A camada de abstração do WASI adiciona overhead pra operações de arquivo/rede
  • Computação prolongada: Código nativo com SIMD e threading ainda é mais rápido pra processamento longo
  • GPU: Sem acesso GPU via WASI, treinar IA e gráficos ficam de fora

Bora codar: sua primeira app WASI

Usando Spin (por Fermyon)

A forma mais rápida de começar com Wasm no servidor:

# Instalar Spin curl -fsSL https://developer.fermyon.com/downloads/install.sh | bash # Criar projeto spin new -t http-rust my-api cd my-api

O código gerado:

// src/lib.rs use spin_sdk::http::{IntoResponse, Request, Response}; use spin_sdk::http_component; #[http_component] fn handle_request(req: Request) -> anyhow::Result<impl IntoResponse> { let path = req.uri().path(); match path { "/" => Ok(Response::builder() .status(200) .header("content-type", "application/json") .body(r#"{"status": "ok", "runtime": "wasm"}"#)?), "/heavy-compute" => { // Roda com velocidade quase nativa let result = fibonacci(40); Ok(Response::builder() .status(200) .body(format!(r#"{{"fib40": {}}}"#, result))?) } _ => Ok(Response::builder() .status(404) .body("Not found")?), } } fn fibonacci(n: u64) -> u64 { match n { 0 => 0, 1 => 1, _ => fibonacci(n - 1) + fibonacci(n - 2), } }
# spin.toml spin_manifest_version = 2 [application] name = "my-api" version = "0.1.0" [[trigger.http]] route = "/..." component = "my-api" [component.my-api] source = "target/wasm32-wasip2/release/my_api.wasm" [component.my-api.build] command = "cargo build --target wasm32-wasip2 --release"
# Compilar e rodar localmente spin build spin up # Testar curl http://localhost:3000/ # {"status": "ok", "runtime": "wasm"} # Deploy pro Fermyon Cloud (grátis) spin deploy

Usando wasmtime diretamente

Pra mais controle:

# Instalar wasmtime curl https://wasmtime.dev/install.sh -sSf | bash # Compilar sua app Rust com target WASI rustup target add wasm32-wasip2 cargo build --target wasm32-wasip2 --release # Rodar wasmtime run target/wasm32-wasip2/release/myapp.wasm

O ecossistema de ferramentas em 2026

Runtimes

RuntimeFocoProduçãoNotas
WasmtimePropósito geralBytecode Alliance, o mais maduro
WasmerUniversalRegistry, WAPM, gerenciador de pacotes
WasmEdgeEdge/AIProjeto CNCF, suporte ONNX
SpinServerlessFermyon, melhor DX
WazeroEmbedding em GoPure Go, sem CGo

Suporte por linguagem

Nem toda linguagem tá igualmente preparada pro desenvolvimento WASI:

LinguagemComponent ModelWASI 0.3Maturidade
Rust✅ CompletoProdução
Go (TinyGo)Produção
Python (componentize-py)⚠️ ParcialBeta
JavaScript (ComponentizeJS)⚠️ ParcialBeta
C/C++Produção
C#/.NET✅ (experimental)⚠️Alpha

Ferramentas principais

# wasm-tools: o canivete suíço do Wasm cargo install wasm-tools # Inspecionar um componente wasm-tools component wit myapp.wasm # Compor componentes wasm-tools compose main.wasm --adapt adapter.wasm -o composed.wasm # jco: JavaScript Component Tools npm install -g @bytecodealliance/jco # Converter componente Wasm pra módulo JS jco transpile component.wasm -o output/ # cargo-component: Compilar componentes Rust cargo install cargo-component cargo component new my-component cargo component build

Como fica na prática: arquitetura com Component Model

Um exemplo de arquitetura real usando componentes Wasm:

┌─────────────────────────────────────────────────────────┐
│                    API Gateway                           │
│                   (Componente Wasm)                      │
│                                                         │
│  ┌─────────────┐  ┌──────────────┐  ┌──────────────┐  │
│  │ Auth        │  │ Rate Limiter │  │ Logger       │  │
│  │ (Rust)      │  │ (Go)         │  │ (Python)     │  │
│  │ Componente  │  │ Componente   │  │ Componente   │  │
│  └──────┬──────┘  └──────┬───────┘  └──────┬───────┘  │
│         └────────────────┼──────────────────┘          │
│                          ▼                              │
│  ┌──────────────────────────────────────────────────┐  │
│  │              Lógica de Negócio                     │  │
│  │              (Qualquer linguagem)                 │  │
│  │              ┌──────────────────┐                 │  │
│  │              │ Processador de   │                 │  │
│  │              │ Imagens (Rust)   │                 │  │
│  │              └──────────────────┘                 │  │
│  └──────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────┘

Cada componente:

  • Escrito na melhor linguagem pra sua tarefa
  • Sandboxed com só as permissões necessárias
  • Composável com outros componentes via interfaces WIT
  • Hot-swappable sem reiniciar o host

Pegadinhas que você vai querer evitar

1. "É só compilar minha app Node.js pra Wasm"

Não funciona assim. APIs do Node.js não existem no WASI. Use frameworks feitos pra isso como Spin ou WasmCloud.

2. Esperar compatibilidade POSIX completa

WASI não é POSIX. É uma interface nova e mínima. fork(), memória compartilhada, sinais... nada disso existe. Projete pro modelo WASI, não tente portar apps Linux direto.

3. Tamanho do binário

Binários Wasm podem ficar grandes sem otimização:

# Rust: otimizado pra tamanho [profile.release] opt-level = "s" # Otimizar pra tamanho lto = true # Link-time optimization strip = true # Remover info de debug codegen-units = 1 # Melhor otimização # Resultado: ~5MB → ~500KB

4. Nem toda linguagem rende igual

Rust e C/C++ geram o melhor Wasm. Go (via TinyGo) funciona bem mas tem limitações. Python e JavaScript passam por interpretadores compilados pra Wasm, com o overhead que isso traz.


O que vem por aí

Agora (Q1 2026)

  • ✅ WASI 0.3.0 lançado (I/O assíncrono)
  • ✅ Component Model se estabilizando
  • ✅ Docker Wasm em produção
  • ✅ Cloudflare, Fastly, Fermyon operando em escala

Q2-Q3 2026

  • Proposta de threads pro WASI avançando
  • Registros de componentes (gerenciamento de pacotes pra componentes)
  • Mais suporte de linguagens (componentes Java, Swift, Kotlin)
  • wasi-nn se estabilizando pra inferência AI

H2 2026 - 2027

  • Release estável do WASI 1.0 esperado
  • Proposta de acesso a GPU
  • Adoção mais ampla além do edge computing
  • Potencial integração com scheduling nativo do Kubernetes

A visão final

O objetivo é um mundo onde:

  1. Você escreve código em qualquer linguagem
  2. Compila pra um binário universal (componente Wasm)
  3. Roda em qualquer lugar: browser, servidor, edge, IoT, embarcado
  4. Compõe com outros componentes independente da linguagem
  5. Com segurança por padrão: sandbox, baseado em capabilities, sem autoridade implícita

Solomon Hykes (cofundador do Docker): "Se WASM+WASI existisse em 2008, não teríamos precisado criar o Docker. É tão importante assim."


Resumindo

WebAssembly fora do navegador não é mais promessa — é realidade. Com casos de uso que já funcionam:

  • Edge computing: Cold starts 100-500x mais rápidos que containers
  • Plugins: Sandbox seguro, plugins multi-linguagem
  • Serverless: Boot em microssegundos, footprint em megabytes
  • Composição: Misturar linguagens numa aplicação só via Components

O que fazer:

  1. Hoje: Instala wasmtime e roda um hello world WASI (5 minutos)
  2. Essa semana: Testa Spin pra um endpoint HTTP simples. Deploy grátis pro Fermyon Cloud
  3. Esse mês: Avalia se algum dos seus microsserviços ou edge functions se beneficiaria do cold start e memória do Wasm
  4. Esse trimestre: Explora o Component Model. Cria um sistema de plugins ou compõe componentes de linguagens diferentes

O navegador foi só o começo. Wasm tá comendo a infraestrutura do edge pra dentro. O Component Model é a peça que faltava pra transformar isso de uma tecnologia interessante num shift de plataforma.

O sandbox foi aberto.

WebAssemblyWASIComponent ModelEdge ComputingServerlessRustCloud NativeDockerWeb Development

Explore ferramentas relacionadas

Experimente estas ferramentas gratuitas do Pockit