How Service Extensions Work
When the Orchestrator starts, it loads your Go source code and executes it through an embedded Go runtime. At each configured hook point, the Orchestrator calls your named function, passing anapi parameter that provides access to the full Orchestrator interface — sessions, caches, secrets, identity providers, logging, and more.
Service extension code can be delivered in two ways:
- File reference — point to an external
.gosource file on disk. Preferred for production use because it supports version control, IDE tooling, and independent testing. - Inline code — embed Go source directly in the YAML configuration. Convenient for short, self-contained extensions.
The exact function signature varies by hook point. Some hooks omit the
rw or req parameters, some return an error. Refer to the individual hook pages below or the SDK documentation for each hook’s expected signature.Configuration
Each service extension hook accepts aServiceExtension object with the following structure:
Field Reference
Either
code or file must be provided, but not both.
The Service Extension SDK
The Service Extension SDK is a Go module that provides typed interfaces for interacting with Orchestrator services from within your extension code.- Module:
github.com/strata-io/service-extension - Documentation: pkg.go.dev/github.com/strata-io/service-extension
SDK Interfaces
Theapi parameter passed to your extension function implements the orchestrator.Orchestrator interface, which provides access to all subsystem interfaces:
For complete interface definitions, method signatures, and type details, see the SDK reference on pkg.go.dev.
Hook Points
The Orchestrator provides 30 service extension hook points organized by lifecycle area. Each hook is a field on the relevant configuration object. Select a hook name to see its full signature, parameters, and usage details.API Lifecycle
Custom API endpoints are managed through the Service Extensions area in the Console. In the Console sidebar, select Service Extensions and then API to create, edit, and manage custom API endpoints. APIs are attached to deployments from the deployment’s Settings page alongside applications.
See Custom APIs for the
apis[] configuration and Console UI setup steps.
Proxy App Lifecycle
These hooks are available on apps withtype: proxy:
OIDC App Lifecycle
These hooks are available on apps withtype: oidc:
OIDC Provider Level
SAML App Lifecycle
These hooks are available on apps withtype: saml:
LDAP Provider Lifecycle
These hooks are available on theldapProvider configuration:
Session Lifecycle
Single Logout
Writing a Service Extension
The following example shows aLoadCustomAttrs function that queries an attribute provider for user attributes and stores the results in the session:
file for production deployments — it keeps extension code in version control and enables IDE support. Use inline code for short, self-contained extensions where a separate file adds unnecessary overhead.
Runtime Environment
Service extension code runs through the Orchestrator’s embedded Go runtime. Code is interpreted at runtime — there is no compile step.Available Packages
By default, service extensions have access to:- Go standard library (except
os, which is restricted by default) - Service Extension SDK — packages under
service-extension/providing access to Orchestrator services:orchestrator— access to the Orchestrator instance (session, cache, secrets, connectors, router)session— read and write session attributescache— read and write cache entriessecret— retrieve secrets from configured secret providerslog— structured loggingrouter— request routingidfabric— identity fabric integrationtai— WebSphere Trust Association Interceptor (deprecated)weblogic— WebLogic integration
- Third-party libraries — LDAP, JWT, UUID, AWS SDK, HTML parser, NTLM, secp256k1
Protected Packages
Theos package is restricted by default to prevent file system and process access. To opt in, add it to allowedProtectedPackages:
Best Practices
Error Handling
Always check and handle errors returned by SDK methods. Log errors with sufficient context to diagnose issues in production. A panicking extension can disrupt the Orchestrator’s request processing for the affected hook point.Logging
Use the SDK logger (api.Logger()) instead of fmt.Println or the standard log package. The SDK logger integrates with the Orchestrator’s structured logging pipeline and supports key-value pairs for searchable log entries.
Secrets Management
Useapi.SecretProvider() to retrieve secrets at runtime from configured providers (Vault, AWS Secrets Manager, Azure Key Vault, etc.). Never hardcode credentials, API keys, or certificates in extension code.
Performance
Keep extensions lightweight, especially in hot-path hooks likemodifyRequestSE and modifyResponseSE that execute on every proxied request. Use api.Cache() for expensive lookups to avoid redundant calls to external systems.
HTTP Client Reuse
When making outbound HTTP requests from a service extension, always reuse HTTP clients through theapi.HTTP() interface rather than creating a new http.Client per request. Creating clients per request prevents connection pooling, repeats TLS handshakes, and can lead to socket exhaustion under load.
For most use cases, api.HTTP().DefaultClient() provides a ready-to-use client with sensible defaults:
api.HTTP().SetClient() and api.HTTP().GetClient() to register and retrieve named clients:
Named clients registered with
SetClient persist for the lifetime of the Orchestrator process. Use descriptive names (e.g., "payments-api", "identity-service") to avoid collisions between extensions.Statelessness
Do not rely on global variables or package-level state between requests. The Orchestrator may run multiple instances, and the runtime does not guarantee state persistence across configuration reloads. Useapi.Session() for request-scoped state and api.Cache() for cross-request state.
Testing and Deployment
Follow a staged workflow to minimize risk when deploying service extensions:- Develop locally — write and test your extension code against the SDK interfaces. Use Go tooling (formatting, linting, type checking) during development even though extensions run interpreted.
- Deploy to staging — deploy the extension to a non-production Orchestrator instance connected to test identity providers and backend services.
Static analysis limitations: Because service extensions execute inside the Orchestrator’s embedded runtime with injected SDK interfaces, standard static code analysis tools (SAST, linters with security rules) may not produce meaningful results. The most effective way to validate security behavior is to deploy your extension to a test environment and exercise the actual authentication, authorization, and data-handling scenarios your extension participates in.
- Verify behavior — use structured logging (
api.Logger()) to trace extension execution. Check Orchestrator logs for errors, unexpected behavior, or performance issues. - Promote to production — after verifying correct behavior in staging, deploy the extension to production. Monitor Orchestrator logs after deployment for errors from extension code.
Related Pages
Applications
Application configuration where most SE hooks are defined
Service Extension SDK
Go module source and API documentation