RR as AWS Lambda
RoadRunner can run PHP as an AWS Lambda function.
PHP Worker
Use PHP 8.5 with the sockets extension and Composer 2. This worker returns an HTTP response for each invocation:
<?php
use Spiral\RoadRunner;
ini_set('display_errors', 'stderr');
require __DIR__ . "/vendor/autoload.php";
$worker = RoadRunner\Worker::create();
$psr7 = new RoadRunner\Http\PSR7Worker(
$worker,
new \Nyholm\Psr7\Factory\Psr17Factory(),
new \Nyholm\Psr7\Factory\Psr17Factory(),
new \Nyholm\Psr7\Factory\Psr17Factory()
);
while ($req = $psr7->waitRequest()) {
try {
$resp = new \Nyholm\Psr7\Response();
$resp->getBody()->write("hello world");
$psr7->respond($resp);
} catch (\Throwable $e) {
$psr7->getWorker()->error((string)$e);
}
}Name this file handler.php and put it in the root of your project. Make sure to run:
Application
The application uses v6 plugins, pool/v2, goridge/v4, and the HTTP protobuf messages from api-go/v6. Its RoadRunner module versions match the RoadRunner source build. The adapter follows the protobuf request and response structure in the AWS Lambda example.
We can create a simple application to demonstrate how it works:
You need three files:
main.gowith theEndurecontainer:
plugin.gowith the plugin implementation:
The adapter uses API Gateway HTTP API payload format 2.0 and the HTTP protobuf protocol. It encodes http/v1.Request in Payload.Context and sends raw body bytes in Payload.Body. It decodes response metadata as http/v1.Response. The adapter returns base64 response bodies so API Gateway can restore text and binary data. Form bodies remain raw; the PHP application must parse them if needed.
The execution context sets a 10-second budget for worker acquisition and the initial response. A nonzero Supervisor.ExecTTL gives each stream read a separate 10-second timeout. Cleanup cancels the execution context and drains the result channel. A stream read already in progress can continue until its timeout expires. The pool then kills the worker, reaps the process, and starts a replacement. The handler reserves 10 seconds for cleanup plus a 1-second margin before the Lambda deadline. If too little time remains, the handler returns an error without executing PHP. To allow the full execution budget, set the Lambda timeout above 21 seconds, for example 30 seconds, with additional time for initialization and response delivery.
A config file, which can be embedded into the binary using the
embedpackage:
Here you can take full advantage of RoadRunner: you can include any plugin here and configure it with the embedded config (within reasonable limits).
Use Go 1.27.1. If your project has no go.mod, run go mod init example.com/lambda from the project root. Select the dependencies before building:
The build uses -mod=readonly because Composer's vendor directory does not contain Go modules. AWS Lambda requires an executable named bootstrap at the root of the deployment package. Include a Linux PHP 8.5 executable named php and its shared libraries in lib/, built for Amazon Linux 2023 and x86_64. Run these commands from the project root:
Use the Lambda provided.al2023 runtime and x86_64 architecture. Upload the package and connect it to an API Gateway HTTP API with payload format 2.0. For a direct Lambda test, use an API Gateway v2 HTTP request event, not a string event. API Gateway v2 omits the custom-domain API mapping prefix from rawPath; this adapter uses the path supplied in the event.
Repository with the full example
Notes
There are multiple notes to acknowledge:
Start with one worker per Lambda function to control your memory usage.
Make sure to include the environment variables listed in the code to properly resolve the location of the PHP binary and its dependencies.
Last updated