Deliver the selected runtime architecture
The product needed to run customer-written server-side extensions. An earlier evaluation compared hosted runtimes with an AWS implementation and selected Lambda based on isolation, maturity, data residency, and control over the platform.
I took that decision into implementation. I introduced Crossplane and built the Terraform infrastructure, build workflow, and provisioning integration. The goal was to let the product create functions without a platform engineer configuring cloud resources for each upload.
Separate building code from provisioning resources
The build workflow starts when an extension is uploaded to S3 as <name>/<version>/lambda.zip. EventBridge starts a Step Functions execution, which records the version’s build state in DynamoDB, runs CodeBuild, publishes a container image, and records the resulting image URI.
The provisioning workflow starts after a successful build. The SDK service creates a LambdaFunction claim in Kubernetes, and a Crossplane composition creates the corresponding AWS resources.
That separation keeps image construction and cloud-resource reconciliation independently observable. The SDK consumes the completed build record rather than reconstructing the build process.
Keep the provisioning interface small
The SDK supplies the image and runtime settings through one object. This shortened example uses a fictional API group, image repository, and account:
apiVersion: example.com/v1alpha1kind: LambdaFunctionmetadata: name: example-extensionspec: imageUri: >- 111111111111.dkr.ecr.eu-west-1.amazonaws.com/functions:v1 memorySize: 256 timeout: 20 permissionsBoundaryArn: >- arn:aws:iam::111111111111:policy/function-boundary resourceConfig: region: eu-west-1 compositionSelector: matchLabels: type: containerThe composition creates a function-specific IAM role and applies the supplied permissions boundary. Invocation uses an IAM-authenticated function URL with response streaming enabled. Each function also gets a log group so developers can inspect their extension’s output.
The SDK service has a dedicated Kubernetes role for managing function claims. Customer code executes in the resulting Lambda; it does not receive the SDK’s provisioning role. Platform ownership labels keep the dynamically created resources visible in shared monitoring.
Handle retries and lifecycle edges explicitly
The build workflow checks for an active build or an existing successful version before starting work. It uses a version-scoped lock, handles lock contention, and includes recovery for expired locks. Successful versions have a separate artifact record, allowing repeated events to be recognized.
Cleanup also needed attention when a function object was removed partway through provisioning. The composition declares deletion behavior for its managed resources, and the integration includes cleanup for stale composite objects.
The selected runtime carries constraints: a 15-minute execution limit and cold-start latency. Those belong in the architecture decision because they affect which customer extensions the platform can support.
What changed
The product gained an automated path from extension upload to a running function with its own identity, invocation controls, and logs. The platform team owns the shared build and provisioning machinery; individual functions use the same interface without a manual infrastructure request.