wasmtime-go: embedding the Wasmtime runtime from Go
Go WebAssembly runtime powered by Wasmtime
At a glance
- What is it?
- wasmtime-go is the Bytecode Alliance's Go binding for the Wasmtime WebAssembly runtime, implemented over CGO against Wasmtime's C API with precompiled binaries checked into the repository. The binding is faithful to the Rust API, the platform support is narrow, and the README's release checklist still refers to an older version number.
- Who is it for?
- wasmtime-go suits a Go team that wants to run untrusted WebAssembly inside a host process with Wasmtime's isolation, and that is content to link against CGO rather than to keep a pure Go build. It does not suit a team that needs a static binary, cross-compiles for arm64 or for other platforms, or wants a Go-native runtime with no native dependency.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 7, 2026, and from our analysis. They are not legal advice.
Star history
- bytecodealliance/wasmtime-go921 ★ · +6
| Repository | 2026-10-23 | 2026-11-07 |
|---|---|---|
| bytecodealliance/wasmtime-go | 915 | 921 |
6 Stars in the last 15 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
A Go binding over the Wasmtime C API
wasmtime-go is the Go embedding of Wasmtime, the WebAssembly runtime written in Rust, and it is a Bytecode Alliance project. The homepage is the pkg.go.dev page for the module, and the README points at the API documentation there.
The implementation route is stated plainly: this Go library uses CGO to consume the C API of the Wasmtime project which is written in Rust. So the architecture is a Go package whose exported functions call into a C ABI that is in turn a wrapper over the Rust engine. The Go types mirror the runtime's concepts, but they are projections of them rather than an independent implementation.
That is the right trade for this kind of project. Wasmtime's design decisions, its Cranelift based compilation, its resource accounting and its sandboxing all live on the Rust side, and a binding that re-implemented any of it in Go would immediately diverge. The cost of the projection is that the Go API cannot be reshaped independently, which is why the module path carries a major version and why each release is tied to a specific Wasmtime release.
The version in the tree is v49, matching the module path github.com/bytecodealliance/wasmtime-go/v49 and the module declaration in go.mod, which also declares go 1.18 and depends only on github.com/stretchr/testify for tests.
CGO and three supported targets
The README explains the packaging decision in one paragraph, and it is the most important operational fact in the project.
Precompiled binaries of Wasmtime are checked into this repository on tagged releases, so you will not have to install Wasmtime locally. The consequence follows immediately: this project only works on Linux x86_64, macOS x86_64 and Windows x86_64 currently. Building on other platforms needs you to arrange to build Wasmtime yourself and use the CGO_* environment variables to compile correctly.
Three things follow for an adopter. First, the dependency is not a runtime download: the native library is linked into your binary at build time, so it ships with you. Second, if your target list includes arm64, or a Linux distribution you build on, you are outside the prebuilt path and into the self-built path, which means you need a Rust toolchain in your build image. Third, CGO means the Go toolchain must be able to link against a native library, which rules out a pure static, CGO-free build.
The README states the project has been tested with Go 1.13 or later, while go.mod declares go 1.18. Treat the module declaration as the real requirement, since that is what the toolchain enforces.
Bazel users are supported too, with a go_repository rule pointing at the same import path and the version v49.0.1.
The store and engine come first
The hello world example in the README is the best documentation of the API shape, and its structure is the Wasmtime API structure.
Everything starts with a store, because the comments in the example say that almost all operations in wasmtime require a contextual store argument to share, so you create that first:
// Almost all operations in wasmtime require a contextual `store`
// argument to share, so create that first
store := wasmtime.NewStore(wasmtime.NewEngine())The engine is the compilation and execution engine; the store holds the state that a module instance operates on, including the memory and globals of that instance. Passing the store explicitly to every call is the pattern that lets several instances share one engine without sharing state.
Next, the example converts WebAssembly text format to binary with Wat2Wasm, because compiling modules requires WebAssembly binary input. It then compiles that into a module, which the comment describes as compiled JIT code:
module, err := wasmtime.NewModule(store.Engine, wasm)
check(err)Imports are linked at instantiation. The example creates a Go function with WrapFunc to satisfy the module's imported hello function, and passes it to NewInstance along with the module. After instantiation it looks up the exported run function with instance.GetFunc, checks it is not nil, and calls it with run.Call(store).
The whole exchange of a host function for a guest call is a dozen lines, and the naming maps one to one onto Wasmtime's own documentation, which is both a strength for a user coming from Rust and a mild learning curve for everyone else.
Component model and WASI live behind feature files
The top level of the repository is a flat list of Go files, and the naming pattern in it explains how the binding handles features that the underlying runtime treats as optional.
There are paired files such as component_feat_component_model.go and component_feat_component_model_test.go, component_linker_feat_component_model.go, component_type_feat_component_model.go and component_valtype_feat_component_model.go, linker_feat_wasi.go, and config_feat_cache.go, config_feat_cranelift.go, config_feat_gc.go, config_feat_parallel_compilation.go and config_feat_threads.go. Alongside them are maybe_gc_actual.go and maybe_gc_no.go, plus module_feat_cranelift.go.
The feat suffix is a build tag convention: the feature-gated files are compiled only when the corresponding build constraint is satisfied, and the maybe_gc pair provides two implementations of the same behaviour so that the garbage collection support compiles with or without it. The effect for a user is that some of Wasmtime's capabilities are present in the Go API only in a build configured for them, and the configuration surface is the config_feat_ files, which is where you enable features such as the cache, Cranelift, parallel compilation or threads.
The practical consequence is that the API surface you see in pkg.go.dev is wider than the API surface you can always call. If your application needs the component model or a WASI host, check the build tags and the configuration file rather than assuming the types exist in your build.
Developing against a locally built Wasmtime
The contribution instructions describe a different path from the consumer path, and they are worth reading because they explain how the checked-in binaries are produced.
You clone the project, and you will need a local Wasmtime build available, following the Wasmtime contributing documentation. The specific requirement is to build at least the wasmtime-c-api crate, which at the time of writing would be:
$ cargo build -p wasmtime-c-apiThen you point the library's build at that tree:
$ ./ci/local.sh /path/to/wasmtimeThat creates a build directory holding the compiled libraries and header files, after which you can run the ordinary commands such as go test.
So the repository carries two build systems at once. A consumer pulls a tagged release and gets the checked-in precompiled binaries; a contributor builds Wasmtime from Rust source and links against it locally. The checked-in build/ directory at the top level is the artefact of the first path, and ci/ holds the scripts for both the local build and the download.
The project also notes that the extension has been written mostly by people who are primarily Rust programmers, so there are likely to be some faux pas in terms of Go idioms, and it invites pull requests to make it more idiomatic. That is a candid admission that the Go API is a translation of a Rust API rather than a Go-native design.
Version 49, an untagged release stream and a stale checklist
On maintenance, the facts are thin but current enough to judge. The repository is not archived and the last push was on 2026-09-21. There are no GitHub releases, so the version history lives in the module path and the tags rather than in a release list.
The current line is v49. The README's installation instruction is go get -u github.com/bytecodealliance/wasmtime-go/[email protected], and the Bazel rule names the same version. The build directory in the tree holds the precompiled native binaries for the tagged release, and the CI workflow and a coverage badge are present, so the project is still being worked on.
The release checklist at the bottom of the README is worth reading twice, because it shows both the process and a documentation drift. The steps are: run ci/download-wasmtime.py, run go test, then a sed command that rewrites the major version string across the tracked files, download the Wasmtime artefacts again, test, and finally commit and tag the release. The commit message in the example is v49.0.0 release artifacts and the tag is v49.0.0, while the install instruction says v49.0.1. The checklist is a template that has not been updated for the latest point release.
Two conclusions follow. The major version is the thing that changes in the module path, so a v49 to v50 move is an import path change across your codebase and a recompile against a new native library. And because the native binaries are committed, the size of your Go binary grows by the size of Wasmtime, which is a real consideration for a service that ships as a static binary to many machines.
Editorial conclusion
wasmtime-go suits a Go team that wants to run untrusted WebAssembly inside a host process with Wasmtime's isolation, and that is content to link against CGO rather than to keep a pure Go build. It does not suit a team that needs a static binary, cross-compiles for arm64 or for other platforms, or wants a Go-native runtime with no native dependency. Before adopting, run go get -u github.com/bytecodealliance/wasmtime-go/[email protected] on a machine matching one of the three supported targets, build the hello world example from the README, and check the size of the native library your binary now carries, because the precompiled Wasmtime binaries are linked in rather than fetched at run time.
Frequently asked questions
How do I install wasmtime-go?
Run go get -u github.com/bytecodealliance/wasmtime-go/[email protected]. The library uses CGO to consume the C API of Wasmtime, and precompiled binaries of Wasmtime are checked into the repository on tagged releases, so you do not need to install Wasmtime yourself.
Which platforms does wasmtime-go support?
Only Linux x86_64, macOS x86_64 and Windows x86_64, because the precompiled Wasmtime binaries are checked in. Building on other platforms requires building Wasmtime yourself and setting the CGO_* environment variables to compile correctly.
How do I call a WebAssembly function from Go with wasmtime-go?
Create a store with wasmtime.NewStore(wasmtime.NewEngine()), convert the module with Wat2Wasm, compile it with NewModule, wrap host functions with WrapFunc, instantiate with NewInstance, then look up the export with instance.GetFunc and invoke it with run.Call(store).
How do I build wasmtime-go from source for development?
Clone the repository, build the wasmtime-c-api crate from Rust with cargo build -p wasmtime-c-api, then run ./ci/local.sh /path/to/wasmtime to create the build directory with the compiled libraries and header files, and run go test as usual.
Does wasmtime-go need CGO and what does that mean for my build?
Yes. The README states the library uses CGO to consume the C API of the Rust Wasmtime project, and the checked-in precompiled binaries mean the native library is linked into your binary rather than fetched at run time, which also rules out a pure Go static build.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/bytecodealliance-wasmtime-go)Star history chart for your README
[](https://hysenlabs.com/projects/bytecodealliance-wasmtime-go)Was this useful?