Skip to content

Fastly Compute@Edge

Deploy EdgeZero applications to Fastly's Compute@Edge platform using WebAssembly.

Prerequisites

Project Setup

When scaffolding with edgezero new my-app, the Fastly adapter includes:

crates/my-app-adapter-fastly/
├── Cargo.toml
├── fastly.toml
└── src/
    └── main.rs

fastly.toml

The Fastly manifest configures your service:

toml
manifest_version = 2
name = "my-app"
language = "rust"
authors = ["you@example.com"]

[local_server]
  [local_server.backends]
    [local_server.backends."origin"]
    url = "https://your-origin.example.com"

Entrypoint

The Fastly entrypoint wires the adapter:

rust
use edgezero_adapter_fastly::dispatch;
use edgezero_core::app::Hooks;
use my_app_core::App;

#[fastly::main]
fn main(req: fastly::Request) -> Result<fastly::Response, fastly::Error> {
    let app = App::build_app();
    dispatch(&app, req)
}

Building

Build for Fastly's Wasm target:

bash
# Using the CLI
edgezero build --adapter fastly

# Or directly with cargo
cargo build -p my-app-adapter-fastly --target wasm32-wasip1 --release

The compiled Wasm binary is placed in target/wasm32-wasip1/release/.

Local Development

Run locally with Viceroy (Fastly's local simulator):

bash
# Using the CLI
edgezero serve --adapter fastly

# Or directly
fastly compute serve --skip-build

This starts a local server at http://127.0.0.1:7676.

Deployment

Deploy to Fastly Compute@Edge:

bash
# Using the CLI
edgezero deploy --adapter fastly

# Or directly
fastly compute deploy

Backends

EdgeZero's Fastly proxy client uses dynamic backends derived from the target URI (host + scheme). You do not need to predeclare backends in fastly.toml for EdgeZero proxying.

rust
use edgezero_adapter_fastly::FastlyProxyClient;
use edgezero_core::proxy::ProxyService;

let client = FastlyProxyClient;
let response = ProxyService::new(client).forward(request).await?;

Logging

Fastly uses endpoint-based logging. Configure logging in edgezero.toml:

toml
[adapters.fastly.logging]
endpoint = "stdout"
level = "info"
echo_stdout = true

To initialize logging manually, call init_logger with explicit settings:

rust
use edgezero_adapter_fastly::init_logger;
use log::LevelFilter;

fn main() {
    init_logger("stdout", LevelFilter::Info, true).expect("init logger");
}

Logging status

Fastly logging is wired when you call init_logger (or run_app); otherwise no logger is installed.

Context Access

Access Fastly-specific APIs via the request context extensions:

rust
use edgezero_core::context::RequestContext;
use edgezero_adapter_fastly::FastlyRequestContext;

async fn handler(ctx: RequestContext) -> Result<Response, EdgeError> {
    // Access Fastly context from extensions
    if let Some(fastly_ctx) = FastlyRequestContext::get(ctx.request()) {
        let client_ip = fastly_ctx.client_ip;
        // ...
    }

    // ...
}

Streaming

Fastly supports native streaming via stream_to_client. The adapter automatically converts Body::stream to Fastly's streaming APIs.

See the Streaming guide for examples and patterns.

Testing

Run contract tests for the Fastly adapter:

bash
# Set up the Wasm runner
export CARGO_TARGET_WASM32_WASIP1_RUNNER="wasmtime run --dir=."

# Run tests
cargo test -p edgezero-adapter-fastly --features fastly --target wasm32-wasip1

Viceroy Issues

If Viceroy reports keychain access errors on macOS, use Wasmtime as the test runner instead.

Manifest Configuration

Configure the Fastly adapter in edgezero.toml. See Configuration for the full manifest reference.

Next Steps

Released under the MIT License.