Serverless
In-memory functions-as-a-service modelled on Lambda, Azure Functions, and Cloud Functions, driven with the real cloud SDKs
aws Lambdaazr Functionsgcp Cloud Functions
Emulates functions-as-a-service — the Lambda/Azure Functions/Cloud Functions control plane where you create a function and invoke it with a payload. Instead of deploying a zip, you register a plain Go function as the handler; an Invoke then runs it in-process and returns its response bytes. That keeps the create/invoke path fast and deterministic while still exercising your production wiring.
Reach for it in tests when your code creates a function, invokes it synchronously, and reads the response — for example verifying an orchestration that fans out to Lambdas, or a caller that depends on a function's output shape — without deploying to a real cloud. You get the function's response back exactly as the SDK would deliver it.
| Provider | Service | SDK-compat | Driver |
|---|---|---|---|
| AWS | Lambda (REST + JSON) | ✓ Live | aws.Lambda |
| Azure | Functions (Function Apps + /api/{name} invoke) | ✓ Live | azure.Functions |
| GCP | Cloud Functions v1 (Create LRO + :call) | ✓ Live | gcp.CloudFunctions |
Drive it with the real SDK#
The recommended path is to point the real SDK at the SDK-compat server. Because there's no real runtime, you register a Go handler so Invoke has something to execute — then the stock Lambda client creates and calls the function unchanged:
import (
"github.com/aws/aws-sdk-go-v2/service/lambda"
lambdatypes "github.com/aws/aws-sdk-go-v2/service/lambda/types"
awsserver "github.com/stackshy/cloudemu/v2/server/aws"
)
cloud := cloudemu.NewAWS()
ts := httptest.NewServer(awsserver.New(awsserver.Drivers{Lambda: cloud.Lambda}))
client := lambda.NewFromConfig(cfg, func(o *lambda.Options) {
o.BaseEndpoint = aws.String(ts.URL)
})
client.CreateFunction(ctx, &lambda.CreateFunctionInput{
FunctionName: aws.String("my-handler"),
Runtime: lambdatypes.RuntimeGo1x,
Role: aws.String("arn:aws:iam::000000000000:role/test"),
Handler: aws.String("main"),
Code: &lambdatypes.FunctionCode{ZipFile: []byte("z")},
})
// Register a Go handler so Invoke has something to run.
cloud.Lambda.RegisterHandler("my-handler", func(ctx context.Context, payload []byte) ([]byte, error) {
return []byte(`{"status":"ok"}`), nil
})
resp, _ := client.Invoke(ctx, &lambda.InvokeInput{
FunctionName: aws.String("my-handler"),
Payload: []byte(`{"key":"value"}`),
})
fmt.Println(string(resp.Payload)) // {"status":"ok"}Same shape with armappservice (Azure) and google.golang.org/api/cloudfunctions/v1 (GCP) — see SDK-Compat Server.
Call the driver directly#
For in-process setup you can skip the HTTP hop. The flow is the same three steps — create, register a handler, invoke — with the driver's own input structs:
import sdriver "github.com/stackshy/cloudemu/v2/services/serverless/driver"
aws.Lambda.CreateFunction(ctx, sdriver.FunctionConfig{
Name: "my-handler", Runtime: "go1.x", Handler: "main",
})
aws.Lambda.RegisterHandler("my-handler", func(_ context.Context, p []byte) ([]byte, error) {
return []byte(`{"ok":true}`), nil
})
out, _ := aws.Lambda.Invoke(ctx, sdriver.InvokeInput{
FunctionName: "my-handler", Payload: []byte(`{}`),
})Invoke returns an InvokeOutput carrying the status code, response payload, and any handler error string. UpdateFunction(ctx, name, config) patches an existing function's configuration in place and returns the updated FunctionInfo.
Behavior & fidelity#
| Behavior | What happens |
|---|---|
| Invoke runs your handler | A function with no handler registered via RegisterHandler has nothing to execute; the handler's returned bytes come straight back as the invocation payload. |
| Handler errors are invocation errors | An error from the handler is reported on the invocation result, not as a transport failure — the same way the real services separate a function error from a call failure. |
| GCP create/delete are long-running | Cloud Functions create and delete return an LRO you poll via Operations.Get, mirroring the real v1 API; :call is the synchronous invoke. |
| Portable-API-only extras | Layers and reserved/provisioned concurrency are not yet on the SDK-compat layer — reach for them through the Portable Go API. |
SDK-compat — Live#
Real lambda, armappservice, and cloudfunctions/v1 clients drive the emulator end-to-end:
| Provider | Coverage |
|---|---|
| AWS Lambda | Function CRUD, versions, aliases, event source mappings, resource policy, tagging, sync invoke |
| Azure Functions | Function-app CRUD plus HTTP invoke |
| GCP Cloud Functions | Create/Delete LROs, get, list, synchronous call |
See SDK-Compat for the full per-operation list.