diff --git a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/code-migration.md b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/code-migration.md
index d15618360..7661caec3 100644
--- a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/code-migration.md
+++ b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/code-migration.md
@@ -12,10 +12,13 @@ Migrate AWS Lambda function code to Azure Functions.
- If runtime is Python or Node.js: **do NOT create function.json files**
- If runtime is .NET (in-process or isolated) or Java: **do NOT hand-author function.json** — bindings metadata is generated from attributes/annotations at build time
+- If runtime is Go: **do NOT create function.json files** — triggers are declared in code via `sdk.FunctionApp()` functional options and indexed by the Go worker at startup. See [runtimes/go.md](runtimes/go.md).
- Use extension bundle version `[4.*, 5.0.0)` in host.json
- Use latest programming model (v4 for JavaScript, v2 for Python)
- **Always use bindings and triggers instead of SDKs** — For blob read/write, use `input.storageBlob()` / `output.storageBlob()` with `extraInputs`/`extraOutputs`. For queues, use `app.storageQueue()` or `app.serviceBusQueue()`. Only use SDK when there is no equivalent binding (e.g., Azure AI, custom HTTP calls)
+ - **Go exception**: The Go worker (preview) supports **triggers only** — the sole output binding is HTTP. All other I/O (blob writes, queue sends, cosmos upserts, service bus sends, event grid publishes, table reads/writes, etc.) uses the Azure SDK for Go with `DefaultAzureCredential`. See [runtimes/go.md](runtimes/go.md#io-outside-of-triggers--use-the-azure-sdk-for-go) for the full SDK-vs-binding capability matrix and idiomatic patterns.
- **Always use the latest supported language runtime** — Consult [supported languages](https://learn.microsoft.com/en-us/azure/azure-functions/supported-languages) and select the newest GA version. Do NOT default to an older LTS version when a newer version is available on Azure Functions.
+- **Preview runtimes require explicit user confirmation** — Go is currently in **public preview** on Azure Functions. Before selecting Go as the target runtime, use `ask_user` to confirm the user accepts a preview runtime (API surface may change; not covered by production SLA). Also verify Core Tools ≥ 4.12 is installed before running `func init --worker-runtime go`.
## Steps
@@ -119,6 +122,7 @@ Load the appropriate runtime reference for the target language:
| Python (v2) | [runtimes/python.md](runtimes/python.md) |
| C# (Isolated Worker) | [runtimes/csharp.md](runtimes/csharp.md) |
| Java | [runtimes/java.md](runtimes/java.md) |
+| Go (preview) | [runtimes/go.md](runtimes/go.md) |
| PowerShell | [runtimes/powershell.md](runtimes/powershell.md) |
## Scenario-Specific Guidance
diff --git a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/global-rules.md b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/global-rules.md
index abf3e3f68..3ad20905a 100644
--- a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/global-rules.md
+++ b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/global-rules.md
@@ -18,6 +18,7 @@ Always use `ask_user` before:
- Selecting Azure region/location
- Deploying infrastructure
- Making breaking changes to existing code
+- **Selecting a preview-status language runtime** (e.g., Go on Azure Functions). Confirm the user accepts that the runtime's API surface may change and is not covered by the production SLA before scaffolding the project.
## Best Practices
@@ -25,6 +26,7 @@ Always use `ask_user` before:
- Prefer managed identity over connection strings
- **Always use the latest supported language runtime** — check [supported languages](https://learn.microsoft.com/en-us/azure/azure-functions/supported-languages) for the newest GA version. Never default to older versions
- **Always prefer bindings over SDKs** — use `input.storageBlob()`, `output.storageBlob()`, `app.storageQueue()`, etc. instead of `BlobServiceClient`, `QueueClient`, or other SDK clients. Only use SDK when no binding exists for the service
+ - **Go exception**: The Azure Functions Go worker (preview) supports **triggers only**; HTTP is the only output binding. All other I/O (blob, queue, cosmos, service bus, event hub, event grid, table, SQL writes) goes through the Azure SDK for Go with `DefaultAzureCredential`. This is intentional and idiomatic for Go — do not attempt to synthesize non-existent Go bindings. See [runtimes/go.md](runtimes/go.md#io-outside-of-triggers--use-the-azure-sdk-for-go).
- Follow Azure naming conventions
- Use Flex Consumption hosting plan for new Functions
diff --git a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/lambda-to-functions.md b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/lambda-to-functions.md
index 9c2e741b8..5fa66a0b4 100644
--- a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/lambda-to-functions.md
+++ b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/lambda-to-functions.md
@@ -21,13 +21,14 @@ Detailed guidance for migrating AWS Lambda functions to Azure Functions.
## Programming Model Mapping
-| AWS Lambda | Azure Functions |
-|------------|-----------------|
-| `exports.handler` | `app.http()`, `app.storageBlob()`, etc. (v4) |
-| `event` object | `request` / `blob` / trigger-specific param |
-| `context` object | `context` (InvocationContext) |
-| `callback` | Return value |
-| `function.json` (v1-v3) | Inline bindings in code (v4 JS, v2 Python) |
+| AWS Lambda | Azure Functions (JS v4 / Python v2) | Azure Functions (Go worker, preview) |
+|------------|-----------------|-----------------|
+| `exports.handler` | `app.http()`, `app.storageBlob()`, etc. (v4) | `app.HTTP(name, handler, opts...)`, `app.Blob(...)`, `app.Queue(...)`, etc. |
+| `event` object | `request` / `blob` / trigger-specific param | Typed struct param (e.g., `bindings.QueueMessage`, `bindings.EventGridEvent`, `*blob.Client` for the blob extension trigger) |
+| `context` object | `context` (InvocationContext) | `context.Context` (with invocation metadata via `sdk.FromContext(ctx)`) |
+| `callback` | Return value | `error` return value (`nil` = success, non-nil = host retries per trigger policy) |
+| `function.json` (v1-v3) | Inline bindings in code (v4 JS, v2 Python) | Declared in code via `sdk.FunctionApp()` + functional options; no `function.json` |
+| Lambda destinations (on failure → SQS/SNS) | Trigger-specific retry + poison queue | Non-nil `error` return → host retries; poison-message behavior per trigger. See [runtimes/go.md](runtimes/go.md) |
## Trigger Mapping
@@ -52,6 +53,7 @@ For language-specific migration rules, correct/incorrect patterns, and code exam
| TypeScript (v4) | [runtimes/typescript.md](runtimes/typescript.md) |
| C# (Isolated Worker) | [runtimes/csharp.md](runtimes/csharp.md) |
| Java | [runtimes/java.md](runtimes/java.md) |
+| Go (preview) | [runtimes/go.md — Lambda Migration Rules](runtimes/go.md#lambda-migration-rules) |
| PowerShell | [runtimes/powershell.md](runtimes/powershell.md) |
## Project Structure
diff --git a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go.md b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go.md
new file mode 100644
index 000000000..c52772607
--- /dev/null
+++ b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go.md
@@ -0,0 +1,100 @@
+# Go — Azure Functions Go Worker Triggers & Bindings
+
+> **Model**: [`github.com/azure/azure-functions-golang-worker`](https://github.com/Azure/azure-functions-golang-worker) (**preview**).
+> No `function.json` — triggers are declared in code via `sdk.FunctionApp()` + functional options.
+> Entry point: `main.go` calling `worker.Start(app)`.
+> Requires **Azure Functions Core Tools ≥ 4.12** (`npm i -g azure-functions-core-tools@4 --unsafe-perm true`).
+
+## Project Layout
+
+**`main.go`, `go.mod`, and `host.json` must live in the same directory** (project root). `func start` runs `go build` from `host.json`'s directory — `.go` files under `src/` produce `no Go files in
` and the build fails. Sub-packages go in `internal//`. This overrides the generic `src/` layout in [lambda-to-functions.md § Project Structure](../lambda-to-functions.md#project-structure). Full layout, anti-pattern, and rules → [go/project-layout.md](./go/project-layout.md).
+
+## Project Setup
+
+Run these commands **from the project root** (see [Project Layout](#project-layout)):
+
+```bash
+func init --worker-runtime go
+# Discover available versions first, then pin explicitly (see note below).
+go list -m -versions github.com/azure/azure-functions-golang-worker
+go get github.com/azure/azure-functions-golang-worker@main
+go mod tidy
+```
+
+`func init --worker-runtime go` generates `host.json`, `local.settings.json`, and `.gitignore`. Verified templates + per-setting reference → [go/setup-templates.md](./go/setup-templates.md).
+
+> ⚠️ **Never hand-author `require ... v0.0.0`** — the module is preview-only, has no `v0.0.0` tag, and sub-packages share the parent's version (no separate `require` lines). Let `go get @main` (or `@vX.Y.Z-preview`) resolve it. Full guidance → [go/version-pinning.md](./go/version-pinning.md).
+
+## Lambda Migration Rules
+
+> Shared rules (bindings over SDKs, latest runtime, identity-first auth) → [global-rules.md](../global-rules.md)
+
+Go-specific:
+- **`main.go`, `go.mod`, `host.json` co-located at project root** — never `src/`. See [Project Layout](#project-layout).
+- **Non-HTTP output bindings unsupported** — use the Azure SDK for Go with `DefaultAzureCredential`.
+- **Wrap every user-spawned goroutine** with `sdk.Recover` / `sdk.RecoverTo`. An unrecovered panic crashes the whole worker.
+- Prefer **core triggers**. Use the **Blob extension trigger** (blank import) only when you need a live `*blob.Client` for streaming.
+- Log with `slog.InfoContext(ctx, ...)`. The SDK's handler attaches `invocation_id`, `function_name`, `trigger_type` automatically.
+
+## Triggers
+
+Each entry links to a runnable `main.go`-style sample. All non-HTTP handlers return `error` — see [Handler Return Values & Retry Semantics](#handler-return-values--retry-semantics) for what the value means.
+
+| Trigger | SDK method | Sample |
+| --- | --- | --- |
+| HTTP | `app.HTTP` | [triggers/http.md](./go/triggers/http.md) |
+| Blob Storage (extension) | `app.Blob` | [triggers/blob.md](./go/triggers/blob.md) |
+| Queue Storage | `app.Queue` | [triggers/queue.md](./go/triggers/queue.md) |
+| Timer | `app.Timer` | [triggers/timer.md](./go/triggers/timer.md) |
+| Event Grid | `app.EventGrid` | [triggers/event-grid.md](./go/triggers/event-grid.md) |
+| Cosmos DB (change feed) | `app.CosmosDB` | [triggers/cosmos.md](./go/triggers/cosmos.md) |
+| Service Bus (queue / topic) | `app.ServiceBusQueue`, `app.ServiceBusTopic` | [triggers/service-bus.md](./go/triggers/service-bus.md) |
+| Event Hubs | `app.EventHub` | [triggers/event-hubs.md](./go/triggers/event-hubs.md) |
+| SQL (change tracking) | `app.SQL` | [triggers/sql.md](./go/triggers/sql.md) |
+
+## I/O Outside of Triggers — Use the Azure SDK for Go
+
+The Go worker is **triggers-only by design** — no input bindings, no non-HTTP output bindings. This is the intentional exception to the "bindings over SDKs" rule in [global-rules.md](../global-rules.md); all non-HTTP I/O uses the Azure SDK for Go with `DefaultAzureCredential`.
+
+## SDK Patterns for I/O
+
+Ground rules (credentials, client lifetime, URL app settings) and per-service samples (Blob, Queue, Table, Cosmos, Service Bus, Event Hubs, Event Grid) → [go/sdk-patterns/README.md](./go/sdk-patterns/README.md).
+
+## Core vs Extension Triggers
+
+Most triggers are **core** (typed payload in gRPC message, no external SDK). **Blob** is the only extension trigger — requires blank import and streaming via `azblob`. Decision table → [go/core-vs-extension.md](./go/core-vs-extension.md).
+
+## Handler Return Values & Retry Semantics
+
+Non-HTTP handlers return `error`; the Functions host interprets the value according to the trigger's built-in retry behavior or configured function-level retry policy. Full per-trigger table (Storage Queue → `-poison`, Service Bus → DLQ, Event Grid → 24 h backoff, Event Hubs / Cosmos → function-level retry policies) → [go/retry-semantics.md](./go/retry-semantics.md).
+
+## Panic Recovery in Goroutines
+
+An unrecovered panic in **any** goroutine terminates the entire worker process and fails every concurrent invocation. Always guard user-spawned goroutines with `sdk.Recover` (best-effort) or `sdk.RecoverTo` (propagates as handler error, triggers host retry). Full patterns including `errgroup` composition → [go/panic-recovery.md](./go/panic-recovery.md).
+
+## Logging
+
+The SDK installs an `slog` handler at package init. Records automatically carry `invocation_id`, `function_name`, `trigger_type`.
+
+```go
+slog.InfoContext(ctx, "processed order", "order_id", id, "amount", amount)
+```
+
+Richer metadata (trace parent, retry count) via `sdk.FromContext(ctx)`. Distributed tracing → upstream [`samples/otelTracing`](https://github.com/Azure/azure-functions-golang-worker/tree/main/samples/otelTracing), [`samples/collectorToAzureMonitor`](https://github.com/Azure/azure-functions-golang-worker/tree/main/samples/collectorToAzureMonitor).
+
+## Build & Hosting Constraints
+
+- **Hosting plan**: Flex Consumption only.
+- **Binary format**: Linux ELF named **exactly `app`** (lowercase, no extension) at the deployment zip root. Host executes `/home/site/wwwroot/app` — any other name/location fails to start. `func pack` produces this; for hand-builds see [go/deployment.md § Hand-building the binary](./go/deployment.md#hand-building-the-binary).
+- **`CGO_ENABLED=0`** — Flex Consumption base image has no C toolchain. Pick pure-Go alternatives (e.g., non-cgo SQLite driver).
+
+## Local Run & Deployment
+
+```bash
+func start # auto-compiles the Go module, hosts locally
+func pack # cross-compiles (`CGO_ENABLED=0 GOOS=linux GOARCH=amd64`) and packages an app-at-root zip
+```
+
+The `func pack` zip works with any Functions deployment path (`azd deploy`, `func azure functionapp publish`, `az functionapp deployment source config-zip`). Full deploy commands and the Windows/`Compress-Archive` executable-bit gotcha → [go/deployment.md](./go/deployment.md).
+
+> Full reference: [Azure Functions Go developer guide](https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-go) — and the [azure-functions-golang-worker README](https://github.com/Azure/azure-functions-golang-worker) / [samples/](https://github.com/Azure/azure-functions-golang-worker/tree/main/samples) for the preview SDK surface.
diff --git a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/core-vs-extension.md b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/core-vs-extension.md
new file mode 100644
index 000000000..d95fdc2cd
--- /dev/null
+++ b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/core-vs-extension.md
@@ -0,0 +1,12 @@
+# Core vs Extension Triggers
+
+Most Go worker triggers are **core** — payload arrives as a typed struct in the gRPC invocation message, no external SDK needed, no explicit activation. **Blob** is the only **extension** trigger today.
+
+| Criterion | Core (HTTP, Timer, Queue, CosmosDB, EventGrid, EventHub, ServiceBus, SQL) | Extension (Blob) |
+| --- | --- | --- |
+| Payload size | Bounded (KB–low MB) | Potentially GBs |
+| External SDK | No | Yes (`azblob`, `azidentity`) |
+| Data in gRPC message | Yes — typed struct | Metadata only; stream via `client.DownloadStream` |
+| Activation | Automatic | Blank import: `_ ".../triggers/blob"` |
+
+**Rule**: prefer core triggers. Use the Blob extension trigger only when you need a live `*blob.Client` for streaming.
diff --git a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/deployment.md b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/deployment.md
new file mode 100644
index 000000000..aadc31062
--- /dev/null
+++ b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/deployment.md
@@ -0,0 +1,52 @@
+# Local Run & Deployment — Go
+
+```bash
+func start # auto-compiles the Go module, hosts locally
+func pack # produces a zip with the cross-compiled `app` binary at the root
+```
+
+Run `func pack` from a directory scaffolded by `func init --worker-runtime go` — it handles the `CGO_ENABLED=0 GOOS=linux GOARCH=amd64` cross-compile and packages the artifact for you. The resulting zip works with any Functions deployment path: `azd deploy`, `func azure functionapp publish`, or [zip push deployment](https://learn.microsoft.com/en-us/azure/azure-functions/deployment-zip-push):
+
+```bash
+az functionapp deployment source config-zip \
+ -g -n --src .zip
+```
+
+## Infrastructure
+
+Go on Flex Consumption requires runtime-specific IaC settings (`runtime.name='go'`, `runtime.version='1.0'`, `http20Enabled=false`, no `FUNCTIONS_WORKER_RUNTIME` app setting). For infrastructure creation and full deployment via `azd up`, hand off to the `azure-prepare` skill. Discover the current Go templates with `functions_template_get(language: "go")`; use a matching published template when available, otherwise generate equivalent Bicep or Terraform with the settings above.
+
+## Hand-building the binary
+
+⚠️ **The compiled binary MUST be named exactly `app`** (lowercase, no extension) and sit at the **root** of the deployment zip. The Flex Consumption host executes `/home/site/wwwroot/app` — any other filename or location fails to start with no useful error.
+
+`func pack` handles this for you. If you build by hand, use one of:
+
+```bash
+# Path A — you invoke `func pack --no-build` afterwards.
+# func pack expects the binary at bin/app (matches its own local layout).
+CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o bin/app .
+func pack --no-build
+
+# Path B — you zip the artifact yourself. Build to app at project root, then zip so `app` is at zip root.
+CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app .
+zip -X deploy.zip app host.json # `-X` preserves Unix perms; add other runtime files as needed
+```
+
+**Anti-patterns** (all fail at start with no diagnostic):
+
+| Command | Produces | Why it fails |
+| --- | --- | --- |
+| `go build .` | `` or `.exe` | Wrong filename |
+| `go build -o myapp .` | `myapp` | Wrong filename |
+| `go build -o app.exe .` | `app.exe` | Windows extension |
+| `go build -o bin/app .` then zipping `bin/` into the archive | `bin/app` at zip root | Binary must be at zip root, not in `bin/` |
+
+## Hand-rolling the zip
+
+If you build the deployment zip yourself (e.g., a Windows CI job that skips `func pack`), the `app` entry must carry Unix executable permissions (mode `0755` or `0777`) in the zip's external attributes — this is a zip-format-level bit, not an NTFS ACL. Windows tools like PowerShell's `Compress-Archive` and Explorer's "Send to → Compressed folder" emit DOS-mode zips with no Unix permission bits; the host will fail to exec `app` on Linux with a permission-denied error.
+
+Use one of:
+- `func pack` — works on any host OS and stamps the bits correctly (preferred).
+- WSL's `zip` (or Linux/macOS `zip -X`).
+- A CI step that explicitly sets the executable bit before/after zipping.
diff --git a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/panic-recovery.md b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/panic-recovery.md
new file mode 100644
index 000000000..4c7c8f14b
--- /dev/null
+++ b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/panic-recovery.md
@@ -0,0 +1,33 @@
+# Panic Recovery in Goroutines — Go
+
+An unrecovered panic in **any** goroutine terminates the entire worker process, failing every concurrent invocation across every function on that worker. Always guard goroutines you start yourself.
+
+**Best-effort work** (`sdk.Recover`) — fire-and-forget, keeps the worker alive:
+
+```go
+go func() {
+ defer sdk.Recover(ctx) // must be the FIRST defer (runs LAST)
+ defer wg.Done()
+ warmCache(ctx)
+}()
+```
+
+**Failure-propagating work** (`sdk.RecoverTo` — preferred pattern uses `errgroup`):
+
+```go
+import "golang.org/x/sync/errgroup"
+
+func onEventHub(ctx context.Context, events []bindings.EventHubMessage) error {
+ g, ctx := errgroup.WithContext(ctx)
+ for _, e := range events {
+ e := e
+ g.Go(func() (err error) {
+ defer sdk.RecoverTo(ctx, &err)
+ return process(ctx, e)
+ })
+ }
+ return g.Wait() // non-nil -> invocation fails -> host retries
+}
+```
+
+See [retry-semantics.md](./retry-semantics.md) for how the returned error is interpreted by the host.
diff --git a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/project-layout.md b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/project-layout.md
new file mode 100644
index 000000000..bb59cde0a
--- /dev/null
+++ b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/project-layout.md
@@ -0,0 +1,39 @@
+# Project Layout
+
+> **Overrides [lambda-to-functions.md § Project Structure](../../lambda-to-functions.md#project-structure).** The `src/`-based layout there is a JS/Python convention and breaks Go builds.
+
+`main.go` and `go.mod` **must sit next to `host.json`** at the project root. `func start` runs `go build` from `host.json`'s directory; `.go` files elsewhere are invisible.
+
+## Required
+
+```
+myapp/
+├── go.mod
+├── go.sum
+├── main.go # entry — calls worker.Start(app)
+├── host.json
+├── local.settings.json
+└── internal/ # OPTIONAL sub-packages
+ ├── handlers/http.go
+ └── store/cosmos.go
+```
+
+## Anti-pattern (breaks `func start`)
+
+```
+myapp/
+├── host.json # build root
+├── go.mod
+└── src/
+ └── main.go # invisible — build fails
+```
+
+Error: `no Go files in ` → `Go build failed with exit code 1.`
+
+## Rules
+
+- **Never use `src/`** — not idiomatic Go, not recognized by `go build`. Matches [go.dev module layout](https://go.dev/doc/modules/layout) and [worker samples](https://github.com/Azure/azure-functions-golang-worker/tree/main/samples).
+- Sub-packages go in **`internal//`** (compiler-private) or top-level named packages (`handlers/`, `store/`). Name by role, not generic buckets.
+- Exactly one `go.mod` per app, at project root.
+- Run all `func` and `go` commands from project root.
+- **Wrapper directory naming**: when the Function app lives inside a wrapper (e.g., alongside migration reports at `-azure/`), name it `func/` or the service name — **never `app/`** (collides with the required binary name `app`, invites hand-zip mistakes like `zip -r deploy.zip app` producing the wrong archive shape). Update `azure.yaml`'s `project:` to match (e.g., `project: ./func`).
diff --git a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/retry-semantics.md b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/retry-semantics.md
new file mode 100644
index 000000000..c63d16dda
--- /dev/null
+++ b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/retry-semantics.md
@@ -0,0 +1,22 @@
+# Handler Return Values & Retry Semantics — Go
+
+Every non-HTTP trigger handler returns `error`. The value is interpreted by the Functions **host** (not the Go worker), so the retry and poison-message behavior is identical to what the same trigger would do in any other runtime:
+
+- `return nil` → invocation succeeds; the host advances the checkpoint / acknowledges the message / commits change-feed progress as appropriate.
+- `return err` (non-nil) → invocation fails. The next action depends on the trigger: its binding extension can retry or dead-letter the event, or a configured function-level retry policy can rerun the failed execution.
+
+| Trigger | Default retry behavior | Poison / dead-letter destination |
+|---------|------------------------|-----------------------------------|
+| HTTP | No automatic retry — response is returned to the caller | N/A (write status code + body in the handler) |
+| Storage Queue | Up to `maxDequeueCount` (default 5) | `-poison` queue |
+| Service Bus Queue / Topic | Up to `MaxDeliveryCount` (default 10, entity-level) | Entity's dead-letter subqueue |
+| Event Grid | Retried by Event Grid (24 h exponential backoff) | Dead-letter destination configured on the subscription |
+| Blob (`sdk.WithSource("EventGrid")`) | Retried by Event Grid, same as above | Dead-letter destination on the Event Grid subscription |
+| Event Hubs | Configurable function-level retry policy. Checkpoints aren't written until the retry policy for the execution finishes, pausing progress on that partition. | No built-in dead-letter destination |
+| Cosmos DB (change feed) | Configurable function-level retry policy reruns a failed execution until success or the maximum retry count is reached. | No built-in dead-letter destination |
+| Timer | No retry — next occurrence fires on schedule | N/A |
+| SQL (change tracking) | Per `host.json` retry policy | Per configured retry sink |
+
+Configure [function-level retry policies](https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-error-pages) for Event Hubs, Cosmos DB, and other supported triggers. Retry policies rerun failed executions; they don't create a poison or dead-letter destination.
+
+**Interaction with panic recovery:** `sdk.RecoverTo` converts a panic in a user-spawned goroutine into a non-nil error on the enclosing handler — which then follows the table above. That's why `sdk.RecoverTo` is the correct choice for "failure should cause a retry"; `sdk.Recover` is for best-effort work where losing the panic (and skipping the retry) is acceptable. See [panic-recovery.md](./panic-recovery.md) for the full pattern.
diff --git a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/sdk-patterns/README.md b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/sdk-patterns/README.md
new file mode 100644
index 000000000..6da8fe0de
--- /dev/null
+++ b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/sdk-patterns/README.md
@@ -0,0 +1,40 @@
+# SDK Patterns for I/O — Ground Rules
+
+The Go worker is triggers-only by design; non-HTTP output uses the Azure SDK for Go directly. All samples in this directory share the credential and client-lifetime rules below.
+
+**Ground rules:**
+
+- Use `DefaultAzureCredential`. On UAMI apps, always pass `ManagedIdentityClientID: os.Getenv("AZURE_CLIENT_ID")` — otherwise it tries SystemAssigned first and fails. See [global-rules.md](../../../global-rules.md).
+- **Construct clients once at package init or in `main`**, not per invocation. The worker hosts many concurrent invocations on one process; per-invocation client construction defeats connection pooling and triggers repeated token acquisition.
+- Point every service at its URL via an app setting (e.g., `STORAGE_BLOB_URI=https://myacct.blob.core.windows.net`) — never embed keys.
+
+```go
+import (
+ "os"
+ "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
+)
+
+var cred = mustCred()
+
+func mustCred() *azidentity.DefaultAzureCredential {
+ c, err := azidentity.NewDefaultAzureCredential(&azidentity.DefaultAzureCredentialOptions{
+ ManagedIdentityClientID: os.Getenv("AZURE_CLIENT_ID"),
+ })
+ if err != nil { panic(err) }
+ return c
+}
+```
+
+The `cred` variable above is shared by every SDK sample in this directory.
+
+## Samples
+
+| Service | Operations | Sample |
+| --- | --- | --- |
+| Blob | read & write | [blob.md](./blob.md) |
+| Queue | send | [queue.md](./queue.md) |
+| Table | read & upsert | [table.md](./table.md) |
+| Cosmos DB | point read & upsert | [cosmos.md](./cosmos.md) |
+| Service Bus | send | [service-bus.md](./service-bus.md) |
+| Event Hubs | send batch | [event-hubs.md](./event-hubs.md) |
+| Event Grid | publish | [event-grid.md](./event-grid.md) |
diff --git a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/sdk-patterns/blob.md b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/sdk-patterns/blob.md
new file mode 100644
index 000000000..b2347e590
--- /dev/null
+++ b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/sdk-patterns/blob.md
@@ -0,0 +1,18 @@
+# Blob — read & write (Azure SDK for Go)
+
+> Shared ground rules (credential setup, client lifetime, URL app settings) → [README.md](./README.md).
+
+```go
+import "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob"
+
+var blobs, _ = azblob.NewClient(os.Getenv("STORAGE_BLOB_URI"), cred, nil)
+
+// Read
+r, err := blobs.DownloadStream(ctx, "input", "path/name.json", nil)
+if err != nil { return err }
+defer r.Body.Close()
+// stream r.Body
+
+// Write
+_, err = blobs.UploadStream(ctx, "output", "path/name.json", body, nil)
+```
diff --git a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/sdk-patterns/cosmos.md b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/sdk-patterns/cosmos.md
new file mode 100644
index 000000000..15d861aa0
--- /dev/null
+++ b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/sdk-patterns/cosmos.md
@@ -0,0 +1,18 @@
+# Cosmos DB — point read & upsert (Azure SDK for Go)
+
+> Shared ground rules (credential setup, client lifetime, URL app settings) → [README.md](./README.md).
+
+```go
+import "github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos"
+
+var cosmos, _ = azcosmos.NewClient(os.Getenv("COSMOS_ENDPOINT"), cred, nil)
+var container, _ = cosmos.NewContainer("mydb", "Items")
+
+// Point read
+pk := azcosmos.NewPartitionKeyString("electronics")
+resp, err := container.ReadItem(ctx, pk, "sku-42", nil)
+
+// Upsert
+raw, _ := json.Marshal(item)
+_, err = container.UpsertItem(ctx, pk, raw, nil)
+```
diff --git a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/sdk-patterns/event-grid.md b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/sdk-patterns/event-grid.md
new file mode 100644
index 000000000..6fac96e25
--- /dev/null
+++ b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/sdk-patterns/event-grid.md
@@ -0,0 +1,20 @@
+# Event Grid — publish (Azure SDK for Go)
+
+> Shared ground rules (credential setup, client lifetime, URL app settings) → [README.md](./README.md).
+
+```go
+import (
+ "os"
+
+ "github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
+ "github.com/Azure/azure-sdk-for-go/sdk/messaging/eventgrid/azeventgrid"
+)
+
+var eg, _ = azeventgrid.NewClient(os.Getenv("EVENTGRID_ENDPOINT"), cred, nil)
+
+events := []azeventgrid.CloudEvent{{
+ Source: to.Ptr("myapp"), Type: to.Ptr("order.created"),
+ Data: order, DataContentType: to.Ptr("application/json"),
+}}
+_, err := eg.PublishCloudEvents(ctx, "mytopic", events, nil)
+```
diff --git a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/sdk-patterns/event-hubs.md b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/sdk-patterns/event-hubs.md
new file mode 100644
index 000000000..aba1efe07
--- /dev/null
+++ b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/sdk-patterns/event-hubs.md
@@ -0,0 +1,14 @@
+# Event Hubs — send batch (Azure SDK for Go)
+
+> Shared ground rules (credential setup, client lifetime, URL app settings) → [README.md](./README.md).
+
+```go
+import "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs"
+
+var producer, _ = azeventhubs.NewProducerClient(
+ os.Getenv("EVENTHUBS_FQDN"), "outhub", cred, nil)
+
+batch, _ := producer.NewEventDataBatch(ctx, nil)
+_ = batch.AddEventData(&azeventhubs.EventData{Body: payload}, nil)
+err := producer.SendEventDataBatch(ctx, batch, nil)
+```
diff --git a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/sdk-patterns/queue.md b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/sdk-patterns/queue.md
new file mode 100644
index 000000000..029d97269
--- /dev/null
+++ b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/sdk-patterns/queue.md
@@ -0,0 +1,19 @@
+# Queue — send (Azure SDK for Go)
+
+> Shared ground rules (credential setup, client lifetime, URL app settings) → [README.md](./README.md).
+
+```go
+import (
+ "encoding/base64"
+ "os"
+
+ "github.com/Azure/azure-sdk-for-go/sdk/storage/azqueue"
+)
+
+var queue, _ = azqueue.NewQueueClient(
+ os.Getenv("STORAGE_QUEUE_URI")+"/outqueue", cred, nil)
+
+_, err := queue.EnqueueMessage(ctx, base64.StdEncoding.EncodeToString(payload), nil)
+```
+
+> Storage Queue messages must be Base64-encoded when written via SDK — the queue trigger binding does this for you, but the SDK does not.
diff --git a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/sdk-patterns/service-bus.md b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/sdk-patterns/service-bus.md
new file mode 100644
index 000000000..9a63da187
--- /dev/null
+++ b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/sdk-patterns/service-bus.md
@@ -0,0 +1,12 @@
+# Service Bus — send (Azure SDK for Go)
+
+> Shared ground rules (credential setup, client lifetime, URL app settings) → [README.md](./README.md).
+
+```go
+import "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus"
+
+var sb, _ = azservicebus.NewClient(os.Getenv("SERVICEBUS_FQDN"), cred, nil)
+var sender, _ = sb.NewSender("outqueue", nil) // or topic name
+
+err := sender.SendMessage(ctx, &azservicebus.Message{Body: payload}, nil)
+```
diff --git a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/sdk-patterns/table.md b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/sdk-patterns/table.md
new file mode 100644
index 000000000..4325e2b83
--- /dev/null
+++ b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/sdk-patterns/table.md
@@ -0,0 +1,19 @@
+# Table — read & upsert (Azure SDK for Go)
+
+> Shared ground rules (credential setup, client lifetime, URL app settings) → [README.md](./README.md).
+
+```go
+import "github.com/Azure/azure-sdk-for-go/sdk/data/aztables"
+
+var tables, _ = aztables.NewServiceClient(os.Getenv("STORAGE_TABLE_URI"), cred, nil)
+var products = tables.NewClient("Products")
+
+// Read one entity
+resp, err := products.GetEntity(ctx, "electronics", "sku-42", nil)
+var p Product
+_ = json.Unmarshal(resp.Value, &p)
+
+// Upsert
+raw, _ := json.Marshal(p)
+_, err = products.UpsertEntity(ctx, raw, nil)
+```
diff --git a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/setup-templates.md b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/setup-templates.md
new file mode 100644
index 000000000..aa9e4a9b5
--- /dev/null
+++ b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/setup-templates.md
@@ -0,0 +1,53 @@
+# Generated `host.json` / `local.settings.json` — Go
+
+Verified output of `func init --worker-runtime go` (Core Tools 4.12.0). The `host.json` matches the shared extension bundle range in [code-migration.md](../../code-migration.md).
+
+## `host.json`
+
+```json
+{
+ "version": "2.0",
+ "logging": {
+ "applicationInsights": {
+ "samplingSettings": {
+ "isEnabled": true,
+ "excludedTypes": "Request"
+ }
+ }
+ },
+ "extensionBundle": {
+ "id": "Microsoft.Azure.Functions.ExtensionBundle",
+ "version": "[4.*, 5.0.0)"
+ }
+}
+```
+
+## `local.settings.json`
+
+```json
+{
+ "IsEncrypted": false,
+ "Values": {
+ "FUNCTIONS_WORKER_RUNTIME": "native",
+ "FUNCTIONS_CLI_NATIVE_LANGUAGE": "go",
+ "AzureWebJobsStorage": ""
+ }
+}
+```
+
+> **`local.settings.json` is local-only** — [Microsoft Learn](https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-go) is explicit: "this file isn't published to Azure." The values above are for `func start`, not for the deployed app:
+> - `FUNCTIONS_WORKER_RUNTIME=native` — tells Core Tools to load the "native" worker; Core Tools infers Go by finding `go.mod`. **On the deployed Flex Consumption app, do NOT set this app setting** — the runtime is controlled by `functionAppConfig.runtime = { name: 'go', version: '1.0' }` on the ARM/Bicep resource. Adding `FUNCTIONS_WORKER_RUNTIME` in Azure will conflict with the Flex `runtime` block.
+> - `FUNCTIONS_CLI_NATIVE_LANGUAGE=go` — written by `func init --worker-runtime go` but redundant in practice (Core Tools infers Go from `go.mod`). Not consumed by the deployed Functions host.
+> - `AzureWebJobsStorage` — leave empty locally when no trigger needs host storage; set to `UseDevelopmentStorage=true` for Azurite. In Azure, use the identity-based form: `AzureWebJobsStorage__blobServiceUri` + `AzureWebJobsStorage__credential=managedidentity` + `AzureWebJobsStorage__clientId=`.
+
+## Deployed app requirements (Flex Consumption)
+
+For the Bicep/Terraform to provision the function app correctly:
+
+- `functionAppConfig.runtime = { name: 'go', version: '1.0' }` (Bicep) / `runtime = { name = "go", version = "1.0" }` (Terraform).
+- `siteConfig.http20Enabled: false` — **required during Go public preview**; deployments without this fail at runtime.
+- Flex Consumption plan (SKU `FC1`) — Consumption / Premium / Dedicated are not supported.
+- Linux only. No Durable Functions. No deployment slots.
+- Do NOT set `FUNCTIONS_WORKER_RUNTIME` as an app setting.
+
+For complete packaging and infrastructure guidance, see [deployment.md](./deployment.md).
diff --git a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/triggers/blob.md b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/triggers/blob.md
new file mode 100644
index 000000000..4e4269b5c
--- /dev/null
+++ b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/triggers/blob.md
@@ -0,0 +1,31 @@
+# Blob Storage Trigger — Go (extension trigger)
+
+```go
+import (
+ "context"
+ "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob"
+ "github.com/azure/azure-functions-golang-worker/sdk"
+ _ "github.com/azure/azure-functions-golang-worker/triggers/blob" // registers factory
+ "github.com/azure/azure-functions-golang-worker/worker"
+)
+
+func onBlob(ctx context.Context, client *blob.Client) error {
+ get, err := client.DownloadStream(ctx, nil)
+ if err != nil { return err }
+ defer get.Body.Close()
+ // stream get.Body — supports GB-scale blobs without buffering through gRPC
+ return nil
+}
+
+func main() {
+ app := sdk.FunctionApp()
+ app.Blob("processBlob", onBlob,
+ sdk.WithPath("samples-workitems/{name}"),
+ sdk.WithConnection("AzureWebJobsStorage"),
+ sdk.WithSource("EventGrid"),
+ )
+ worker.Start(app)
+}
+```
+
+> **`sdk.WithSource("EventGrid")` needs Flex Consumption infrastructure setup.** When the blob trigger uses EventGrid source on Flex Consumption (the only plan Go supports today), three additional IaC settings are required or events will not be delivered: `alwaysReady: [{ name: 'blob', instanceCount: 1 }]`, the `AzureWebJobsStorage__queueServiceUri` app setting, and an Event Grid subscription authored in Bicep/ARM rather than via the `az` CLI. Full Bicep + RBAC checklist: [lambda-to-functions.md — Flex Consumption + Blob Trigger with EventGrid Source](../../../lambda-to-functions.md#flex-consumption--blob-trigger-with-eventgrid-source).
diff --git a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/triggers/cosmos.md b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/triggers/cosmos.md
new file mode 100644
index 000000000..8455a147e
--- /dev/null
+++ b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/triggers/cosmos.md
@@ -0,0 +1,18 @@
+# Cosmos DB Trigger — Go (Change Feed)
+
+```go
+func onChanges(ctx context.Context, docs []bindings.CosmosDocument) error {
+ for _, d := range docs {
+ _ = d.ID
+ _ = d.Data // json.RawMessage — unmarshal into your struct
+ }
+ return nil
+}
+
+app.CosmosDB("docs", onChanges,
+ sdk.WithDatabase("ToDoList"),
+ sdk.WithContainer("Items"),
+ sdk.WithConnection("CosmosDBConnection"),
+ sdk.WithCreateLeaseContainerIfNotExists(true),
+)
+```
diff --git a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/triggers/event-grid.md b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/triggers/event-grid.md
new file mode 100644
index 000000000..78869f18c
--- /dev/null
+++ b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/triggers/event-grid.md
@@ -0,0 +1,10 @@
+# Event Grid Trigger — Go
+
+```go
+func onEvent(ctx context.Context, e bindings.EventGridEvent) error {
+ // e.Id, e.EventType, e.Subject, e.EventTime, e.Data (json.RawMessage)
+ return nil
+}
+
+app.EventGrid("eventGridTrigger", onEvent)
+```
diff --git a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/triggers/event-hubs.md b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/triggers/event-hubs.md
new file mode 100644
index 000000000..66439806c
--- /dev/null
+++ b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/triggers/event-hubs.md
@@ -0,0 +1,14 @@
+# Event Hubs Trigger — Go
+
+```go
+func onEventHub(ctx context.Context, e bindings.EventHubMessage) error {
+ // e.Body, e.SequenceNumber, e.Offset, e.EnqueuedTimeUtc, e.PartitionKey
+ return nil
+}
+
+app.EventHub("eventHubTrigger", onEventHub,
+ sdk.WithEventHubName("input-hub"),
+ sdk.WithConnection("EventHubConnection"),
+ sdk.WithConsumerGroup("$Default"),
+)
+```
diff --git a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/triggers/http.md b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/triggers/http.md
new file mode 100644
index 000000000..0da1d2092
--- /dev/null
+++ b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/triggers/http.md
@@ -0,0 +1,28 @@
+# HTTP Trigger — Go
+
+```go
+import (
+ "net/http"
+ "github.com/azure/azure-functions-golang-worker/sdk"
+ "github.com/azure/azure-functions-golang-worker/worker"
+)
+
+func hello(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write([]byte("Hello from Go!"))
+}
+
+func main() {
+ app := sdk.FunctionApp()
+ app.HTTP("hello", hello,
+ sdk.WithMethods("GET", "POST"),
+ sdk.WithAuth("anonymous"),
+ // sdk.WithRoute("users/{id}"),
+ )
+ worker.Start(app)
+}
+```
+
+> The HTTP output binding is attached implicitly — write the response via `http.ResponseWriter`.
+
+> **HTTP middleware and streaming.** For wrapping handlers with middleware (timing, tracing, auth), see the upstream [`samples/middleware`](https://github.com/Azure/azure-functions-golang-worker/tree/main/samples/middleware) sample. For streaming responses (Server-Sent Events, large-object downloads, chunked transfer), see [`samples/httpStreaming`](https://github.com/Azure/azure-functions-golang-worker/tree/main/samples/httpStreaming) — the HTTP path uses a real loopback `http.Server`, so `http.Flusher`, chunked encoding, and trailers work natively.
diff --git a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/triggers/queue.md b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/triggers/queue.md
new file mode 100644
index 000000000..88712e2aa
--- /dev/null
+++ b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/triggers/queue.md
@@ -0,0 +1,19 @@
+# Queue Storage Trigger — Go
+
+```go
+import (
+ "context"
+ "github.com/azure/azure-functions-golang-worker/sdk"
+ "github.com/azure/azure-functions-golang-worker/sdk/bindings"
+)
+
+func onQueue(ctx context.Context, msg bindings.QueueMessage) error {
+ // msg.Id, msg.Body, msg.DequeueCount, msg.InsertionTime, ...
+ return nil
+}
+
+app.Queue("queueFunc", onQueue,
+ sdk.WithQueueName("myqueue-items"),
+ sdk.WithConnection("AzureWebJobsStorage"),
+)
+```
diff --git a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/triggers/service-bus.md b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/triggers/service-bus.md
new file mode 100644
index 000000000..1d98ad66a
--- /dev/null
+++ b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/triggers/service-bus.md
@@ -0,0 +1,21 @@
+# Service Bus Trigger — Go
+
+```go
+// Queue
+func onSBQueue(ctx context.Context, msg bindings.ServiceBusMessage) error {
+ // msg.MessageId, msg.Body, msg.DeliveryCount, msg.SessionId, ...
+ return nil
+}
+
+app.ServiceBusQueue("queueFunc", onSBQueue,
+ sdk.WithQueueName("input-queue"),
+ sdk.WithConnection("ServiceBusConnection"),
+)
+
+// Topic + Subscription
+app.ServiceBusTopic("topicFunc", onSBQueue,
+ sdk.WithTopicName("orders"),
+ sdk.WithSubscriptionName("processor"),
+ sdk.WithConnection("ServiceBusConnection"),
+)
+```
diff --git a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/triggers/sql.md b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/triggers/sql.md
new file mode 100644
index 000000000..2cb7bee65
--- /dev/null
+++ b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/triggers/sql.md
@@ -0,0 +1,27 @@
+# SQL Trigger — Go (Change Tracking)
+
+> Enable Change Tracking on the DB and table first
+> (`ALTER DATABASE ... SET CHANGE_TRACKING = ON;` then
+> `ALTER TABLE dbo.Products ENABLE CHANGE_TRACKING;`).
+
+```go
+type Product struct {
+ ProductID int `json:"ProductId"`
+ Name string `json:"Name"`
+ Cost int `json:"Cost"`
+}
+
+func onSQL(ctx context.Context, changes []bindings.SQLChange) error {
+ for _, c := range changes {
+ var p Product
+ if err := json.Unmarshal(c.Item, &p); err != nil { continue }
+ _ = c.Operation // Insert | Update | Delete
+ }
+ return nil
+}
+
+app.SQL("productsChanged", onSQL,
+ sdk.WithTable("dbo.Products"),
+ sdk.WithConnection("AzureWebJobsSqlConnectionString"),
+)
+```
diff --git a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/triggers/timer.md b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/triggers/timer.md
new file mode 100644
index 000000000..88239ef4e
--- /dev/null
+++ b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/triggers/timer.md
@@ -0,0 +1,12 @@
+# Timer Trigger — Go
+
+```go
+func onTick(ctx context.Context, t bindings.TimerInfo) error {
+ // t.IsPastDue, t.ScheduleStatus.Last, t.ScheduleStatus.Next
+ return nil
+}
+
+app.Timer("scheduledTask", onTick,
+ sdk.WithSchedule("0 */5 * * * *"),
+)
+```
diff --git a/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/version-pinning.md b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/version-pinning.md
new file mode 100644
index 000000000..3a3deb635
--- /dev/null
+++ b/plugins/azure-skills/skills/azure-cloud-migrate/references/services/functions/runtimes/go/version-pinning.md
@@ -0,0 +1,29 @@
+# Pinning the Golang Worker Module Version
+
+The worker module is preview-only, and its tagged `vX.Y.Z-preview` releases often lag active development on `main`. Never hand-author the `require` line — always let the Go toolchain resolve and write it.
+
+## Enumerate available versions first
+
+```bash
+go list -m -versions github.com/azure/azure-functions-golang-worker
+```
+
+Or check the [Releases page](https://github.com/Azure/azure-functions-golang-worker/releases). Inspect the latest tag's date against activity on `main`.
+
+## Pick a pin strategy
+
+| Situation | Command |
+| --- | --- |
+| Latest preview tag looks recent | `go get github.com/azure/azure-functions-golang-worker@v0.6.0-preview` (substitute current tag) |
+| Latest tag looks stale relative to `main` | `go get github.com/azure/azure-functions-golang-worker@main` (resolves to a pseudo-version like `v0.6.1-0.20260721153000-abcdef123456`) |
+| Reproducing a known-good commit | `go get github.com/azure/azure-functions-golang-worker@` |
+
+## Never do this
+
+Do **not** author `require github.com/azure/azure-functions-golang-worker v0.0.0` (or any unresolved version) by hand. `go mod tidy` fails with:
+
+```
+reading github.com/azure/azure-functions-golang-worker/go.mod at revision v0.0.0: unknown revision v0.0.0
+```
+
+The same rule applies to every sub-package import (`.../sdk`, `.../worker`, `.../triggers/blob`, `.../sdk/bindings`, etc.) — they share the parent module's version, so **do not add separate `require` lines for them**. One `go get` on the root module pins them all.