Upgrading to Bref 3.0
Read the Bref 3.0 release announcement to learn about all the new features and improvements.
Updating dependencies
PHP 8.2 required
Bref 3.0 now requires PHP 8.2 or greater.
Composer Dependencies
Update all Bref packages in your composer.json file from ^2 to ^3, for example:
"require": {
"bref/bref": "^3",
"bref/laravel-bridge": "^3", // if you use Laravel
"bref/symfony-bridge": "^3", // if you use Symfony
"bref/extra-php-extensions": "^3" // if you use extra extensions
}Only update the versions for the packages you actually have in your project.
If you use bref/extra-php-extensions (opens in a new tab), note that it jumps from v1 to v3 (there is no v2). The v1 version was used with Bref v2, and v3 is aligned with Bref v3.
Then run:
composer update --with-all-dependenciesPHP extension changes
The following improvements in Bref 3.0 let you clean up old configurations.
PostgreSQL extension is enabled by default
The PostgreSQL PDO extension (pdo_pgsql) is now enabled by default in Bref layers.
If you had enabled it manually via a php.ini file, you can remove that line:
-extension=pdo_pgsqlRedis extension is now built-in
The Redis PHP extension is now included in Bref layers by default.
If you were using the Redis extension from bref/extra-php-extensions (opens in a new tab), remove the layer from your serverless.yml:
functions:
api:
# ...
layers:
- - ${bref-extra:redis-php-84}And enable the extension via a php.ini file in your project (php/conf.d/php.ini):
extension=redisIf Redis was the only bref/extra-php-extensions extension you were using, you can uninstall the package:
composer remove bref/extra-php-extensionsContainer image changes
If you deploy using container images, you must update your Dockerfile.
If you don't have a Dockerfile in your project, you can skip this section.
Since Bref container images have been merged into a single bref/php-xx image, the following images don't exist anymore: bref/php-xx-fpm and bref/php-xx-console.
Option 1: Set BREF_RUNTIME in the Dockerfile
The simplest upgrade path is to update your Dockerfile to use the unified image and set the runtime:
- FROM bref/php-84-fpm:2
+ FROM bref/php-84:3
+ ENV BREF_RUNTIME=fpm
# ...Replace fpm with function or console depending on your use case.
Option 2: Use one image for all function types (recommended)
A major benefit of v3 is that you can now use a single Docker image for all your functions (web, console, queues, etc.) and set BREF_RUNTIME per function in serverless.yml.
Dockerfile (single image for everything):
FROM bref/php-84:3
# Your application code
COPY . /var/task
# No BREF_RUNTIME set here!serverless.yml (set runtime per function):
functions:
web:
image:
name: my-app-image
environment:
BREF_RUNTIME: fpm # Web/HTTP function
events:
- httpApi: '*'
console:
image:
name: my-app-image
environment:
BREF_RUNTIME: console # Console commands
worker:
image:
name: my-app-image
environment:
BREF_RUNTIME: function # Queue worker
events:
- sqs:
arn: !GetAtt MyQueue.ArnThis approach lets you build and deploy a single Docker image for all function types, simplifying your deployment pipeline.
Local development images
If you use the bref/php-84-fpm-dev image for local development, update it to:
- FROM bref/php-84-fpm-dev:2
+ FROM bref/php-84-dev:3You can then set BREF_RUNTIME environment variable in your docker-compose.yml file or in the Dockerfile directly.
Smaller breaking changes that might impact you
The changes below should not impact the majority of users. However, if you are using any of these features, you might need to update your code.
Changed the AWS account ID for AWS Lambda layers
The AWS account ID where Bref layers are published is different for v3. That lets us keep releasing Bref v2 layers without mixing up layer numbers. If you reference the layers via their full ARN, you must update the Bref AWS account number to 873528684822 (instead of 534081306603).
# Bref v2 layer
arn:aws:lambda:us-east-1:534081306603:layer:php-84:xxx
# Bref v3 layer
arn:aws:lambda:us-east-1:873528684822:layer:php-84:xxxIf you don't know what that means, you're likely not concerned by this change.
If you're not sure, search for 534081306603 in your codebase and replace it with the new account ID.
AWS Lambda layers have been merged into a single layer
If you configure the runtime in your functions using the following syntax:
functions:
web:
# ...
runtime: php-84-fpm # or `php-xx` or `php-xx-console`✅ you have nothing to do, your configuration is valid for Bref v3.
However, if you specify AWS Lambda layers explicitly in serverless.yml (or through any other deployment method), for example:
functions:
web:
# ...
runtime: provided.al2
layers:
- ${bref:layer.php-84}
# or:
- ${bref:layer.php-84-fpm}
# or:
layers:
- 'arn:aws:lambda:us-east-1:534081306603:layer:php-84:21'Then you must update your configuration.
Under the hood, all layers have been merged into one, i.e. php-xx-fpm and php-xx-console have been merged into php-xx to make Bref layers simpler. The runtime is now defined via an environment variable that is automatically injected by Bref when using the runtime: syntax.
-
Option 1: switch to using the simpler
runtime:syntax.Before:
serverless.ymlfunctions: web: # ... runtime: provided.al2 layers: - ${bref:layer.php-84} # or: - ${bref:layer.php-84-fpm} # or: - ${bref:layer.php-84-console}After:
serverless.ymlfunctions: web: # ... runtime: php-84 # or: runtime: php-84-fpm # or: runtime: php-84-consoleThe examples above assume you are using PHP 8.4 (
php-84) but you can replace84with another PHP version.If you include additional layers, you can keep them without issues, for example:
serverless.ymlfunctions: web: # ... runtime: php-84-fpm layers: - ${bref-extra:imagick-php-84} -
Option 2: change the layer names and define the
BREF_RUNTIMEenvironment variable.Before:
serverless.ymlfunctions: web: # ... runtime: provided.al2 layers: - ${bref:layer.php-84} # or: - ${bref:layer.php-84-fpm} # or: - ${bref:layer.php-84-console}After:
serverless.ymlfunctions: web: # ... runtime: provided.al2 layers: - ${bref:layer.php-84} environment: # ... BREF_RUNTIME: function # for ${bref:layer.php-xx} # or BREF_RUNTIME: fpm # for ${bref:layer.php-xx-fpm} # or BREF_RUNTIME: console # ${bref:layer.php-xx-console}The examples above assume you are using PHP 8.4 (
php-84) but you can replace84with another PHP version.
The vendor/bin/bref CLI has been removed
The vendor/bin/bref CLI has been completely removed in Bref 3.0. This is a minor change since the CLI was already 90% removed in Bref 2.0 - only the bref init command remained for bootstrapping new projects.
We now have better onboarding with improved documentation. Here are the alternatives:
- Scaffolding new projects: Follow the getting started guide to create your
serverless.ymlmanually. - Layer versions: Visit runtimes.bref.sh (opens in a new tab) or run
serverless bref:layers. - Running console commands: Use
serverless bref:cli(unchanged from v2). - Local development: Use Docker-based local development.
The hooks system has been removed
The deprecated hooks system has been removed. This change affects very few users (less than 1%) as it was a low-level API used primarily by framework integrations.
If you were using Bref::beforeStartup() or Bref::beforeInvoke(), you must migrate to the BrefEventSubscriber pattern:
Before:
use Bref\Bref;
Bref::beforeStartup(function () {
// Setup code
});After:
use Bref\Bref;
use Bref\Listener\BrefEventSubscriber;
class MyEventSubscriber extends BrefEventSubscriber
{
public function beforeStartup(): void
{
// Setup code
}
}
Bref::events()->subscribe(new MyEventSubscriber());The BrefEventSubscriber class provides additional hooks: afterStartup(), beforeInvoke(), and afterInvoke(). This refactor powers better integrations like the Laravel bridge (opens in a new tab), X-Ray integration (opens in a new tab), and Sentry integration (opens in a new tab).
SOAP extension is now disabled by default
The SOAP PHP extension is now disabled by default. It had very little usage, and disabling it helped reduce layer sizes to make room for more commonly used extensions.
If you need the SOAP extension, you can enable it by creating a php.ini file in your project:
extension=soapAnd reference it in your serverless.yml:
provider:
environment:
BREF_AUTOLOAD_PATH: php/conf.dLaravel version compatibility
If you are using Laravel with Bref, note that:
- Laravel 10, 11, or 12 is required (Laravel 8 and 9 are no longer supported).
- Update
bref/laravel-bridgeto the latest version.
The Laravel bridge has been updated to use the new BrefEventSubscriber pattern internally, but this change is transparent to users.
CloudWatch log formatter enabled by default
The Bref Monolog formatter (opens in a new tab) is now enabled by default in the Laravel and Symfony bridges.
This changes how your logs will look. Logs now use a hybrid format that combines human-readable text with structured JSON:
Before (plain text):
[2025-12-05 10:30:45] production.ERROR: Database connection failedAfter (structured format):
ERROR Database connection failed {"message":"Database connection failed","level":"ERROR","context":{...}}This format makes logs easier to read in CloudWatch and enables powerful filtering with CloudWatch Logs Insights (e.g., filter by log level or exception class).
Exception handling is greatly improved: Previously, exception stack traces were split across multiple CloudWatch log records (one per line), making them difficult to read and browse. Now, the entire exception (including stack trace) is grouped in a single JSON object, making debugging much easier.
If you prefer the old format, you can disable the formatter in your Laravel or Symfony configuration. See the Bref Monolog documentation (opens in a new tab) for details.
Locale files from glibc langpacks are no longer included
If you are using intl / ICU (opens in a new tab) for locale-aware formatting (dates, numbers, currencies) or translations, you don't need to do anything as ICU is fully supported in Bref v3. Modern frameworks (Laravel, Symfony…) use ICU, not gettext. That means most users are not affected.
If you are using PHP's native gettext (opens in a new tab) functions or rely on setlocale() with specific locales (e.g. for
strftime()), glibc locale files are no longer included in Amazon Linux 2023 (AL2023). These will no longer work in Bref v3. You may either:
- Switch to using
intl/ ICU, which is the modern standard for translations in PHP and is fully supported in Bref v3. - Or, if you want to keep using
gettextorsetlocale(), switch to container deployments and use a custom Docker image that includes the necessary locale files:
# Install the locale packages you need (e.g. English and French)
RUN microdnf update -y && \
microdnf install -y glibc-langpack-en glibc-langpack-fr && \
microdnf clean allThat's it! Read the Bref 3.0 release announcement to learn more about all the new features and improvements in this release.