Testing Locally
January 20, 2026 ยท View on GitHub
Before deploying to Fastly, test your service locally using a Compute runtime emulator. Two options are available:
Both run your WebAssembly binary locally and emulate the Compute runtime APIs.
Viceroy
Installing Viceroy
From Releases:
# macOS (Apple Silicon)
curl -L https://github.com/fastly/Viceroy/releases/latest/download/viceroy_darwin-arm64.tar.gz | tar xz
# macOS (Intel)
curl -L https://github.com/fastly/Viceroy/releases/latest/download/viceroy_darwin-amd64.tar.gz | tar xz
# Linux
curl -L https://github.com/fastly/Viceroy/releases/latest/download/viceroy_linux-amd64.tar.gz | tar xz
sudo mv viceroy /usr/local/bin/
Via Homebrew:
brew install fastly/tap/viceroy
From Source:
cargo install viceroy
Running Viceroy
# Build your service
zig build -Doptimize=ReleaseSmall
# Run with config file
viceroy --config fastly.toml zig-out/bin/service.wasm
# Or without config (limited features)
viceroy zig-out/bin/service.wasm
# Custom port
viceroy --addr 127.0.0.1:8080 zig-out/bin/service.wasm
Viceroy starts at http://127.0.0.1:7878 by default.
Fastlike
Installing Fastlike
From Releases:
Download from GitHub releases.
From Source:
go install github.com/avidal/fastlike@latest
Running Fastlike
# Build your service
zig build -Doptimize=ReleaseSmall
# Run with config
fastlike -config fastly.toml zig-out/bin/service.wasm
# Custom port
fastlike -addr 127.0.0.1:8080 zig-out/bin/service.wasm
Configuration
Both tools use fastly.toml for configuration. Create this file in your project root:
manifest_version = 3
name = "my-edge-service"
description = "My Fastly Compute service"
language = "other"
[scripts]
build = "zig build -Doptimize=ReleaseSmall && mkdir -p bin && cp zig-out/bin/service.wasm bin/main.wasm"
[local_server]
[local_server.backends]
[local_server.backends.origin]
url = "https://httpbin.org"
[local_server.backends.api]
url = "https://api.example.com"
Backend Configuration
Define backends your service will proxy to:
[local_server.backends]
[local_server.backends.origin]
url = "https://httpbin.org"
override_host = "httpbin.org"
[local_server.backends.api]
url = "https://api.example.com"
override_host = "api.example.com"
Geolocation
Configure mock geolocation data for testing:
[local_server.geolocation]
[local_server.geolocation.addresses]
[local_server.geolocation.addresses."127.0.0.1"]
as_name = "Test ISP"
city = "San Francisco"
country_code = "US"
latitude = 37.7749
longitude = -122.4194
Dictionaries
Set up edge dictionaries:
[local_server.dictionaries]
[local_server.dictionaries.config]
file = "config.json"
format = "json"
Create config.json:
{
"api_key": "test-key-123",
"feature_flag": "enabled"
}
KV Stores
Configure key-value stores:
[local_server.object_stores]
[local_server.object_stores.my_store]
[local_server.object_stores.my_store.key1]
data = "value1"
[local_server.object_stores.my_store.key2]
file = "data/key2.txt"
ACLs
Set up access control lists:
[local_server.acls]
[local_server.acls.blocklist]
file = "acl.json"
Create acl.json:
{
"entries": [
{"prefix": "192.168.1.0/24", "action": "BLOCK"},
{"prefix": "10.0.0.0/8", "action": "ALLOW"}
]
}
Logging Endpoints
[local_server.log_endpoints]
[local_server.log_endpoints.access_log]
file = "access.log"
Making Requests
Test with curl:
# Simple GET
curl http://127.0.0.1:7878/
# With headers
curl -H "X-Custom: value" http://127.0.0.1:7878/path
# POST with body
curl -X POST -d '{"key":"value"}' http://127.0.0.1:7878/api
# See response headers
curl -i http://127.0.0.1:7878/
Debugging
Print Output
Use std.debug.print to log to the console:
const std = @import("std");
fn start() !void {
std.debug.print("Request received\n", .{});
// ...
}
Verbose Mode
Run with verbose output for more debugging info:
viceroy -v zig-out/bin/service.wasm
Development Workflow
A typical development loop:
# Terminal 1: Watch and rebuild
watchexec -e zig "zig build -Doptimize=ReleaseSmall"
# Terminal 2: Run the emulator
viceroy --config fastly.toml zig-out/bin/service.wasm
# Terminal 3: Test
curl http://127.0.0.1:7878/
Limitations
Local emulators approximate the Fastly Compute environment but have differences:
- Performance: Local execution doesn't reflect edge latency or throughput
- Geolocation: Returns mock data unless configured
- Caching: Simulated; doesn't persist across restarts
- Rate limiting: Uses local state only
Test on Fastly's actual platform before production deployment.
Next Steps
- Deployment - Deploy to Fastly Compute
- Error Handling - Debug errors