Deployment
Bref is designed out of the box to deploy using serverless.yml.
Bref can also work with any other deployment tool: Terraform, CloudFormation, SAM, AWS CDK , Pulumi… However, the documentation and user experience are optimized for serverless.yml.
Deploying manually
To deploy to AWS an application configured with serverless.yml, run:
Bref Cloud
bref deployA .serverless/ directory will be created. You can add it to .gitignore.
Deploying for production
In the previous step, we deployed the project installed on your machine. This is probably a development version.
For production, we usually don’t want to deploy:
- dev dependencies
- dev configuration
- etc.
Instead, let’s remove development dependencies and optimize Composer’s autoloader for production:
composer install --prefer-dist --optimize-autoloader --no-devNow is also the best time to configure your project for production, as well as build any file cache if necessary.
Once your project is ready, you can deploy via the following command:
Bref Cloud
bref deployReducing package size
AWS Lambda has a 250MB size limit for deployed applications (unzipped). The limit counts the application code and the Lambda layers: Bref’s PHP runtime layer takes about 90MB of it, so your code has roughly 160MB. Large Composer dependencies can push your project over this limit and also lead to slower cold starts.
A deployment over the limit fails with the AWS error Unzipped size must be smaller than 262144000 bytes.
Extra layers, like extra PHP extensions, count toward the limit too. When a deployment adds a layer and fails, deploying smaller code may keep failing with the same total: CloudFormation updates the function’s layers before its code, so the size check still counts the previous code. Deploy in two steps instead: first the smaller code without the new layer, then add the layer.
The most common offender is aws/aws-sdk-php: it ships clients for every AWS service, adding over 100MB to your vendor directory. If you only use a few services (e.g. S3, SQS, DynamoDB), you can remove the rest.
Add the following to your composer.json:
{
"scripts": {
"pre-autoload-dump": [
"Aws\\Script\\Composer\\Composer::removeUnusedServices"
]
},
"extra": {
"aws/aws-sdk-php": [
"Lambda",
"S3",
"Sqs",
"DynamoDb"
]
}
}Then run composer install (or composer update) to apply the changes. Adjust the list to keep only the AWS services your application actually uses. The services required by the SDK core (like S3 and Sts) are always kept.
Read more in the aws/aws-sdk-php documentation.
As an alternative, you can replace aws/aws-sdk-php with AsyncAws , a lighter SDK that only installs the services you need.
Using google/apiclient? A similar approach is available: see the documentation to remove unused Google API services .
To further reduce deployment size, exclude non-essential files (tests, assets, node_modules) from the package. Read more in the serverless.yml exclusions documentation.
If your application still exceeds the 250MB limit, you can deploy via Docker images instead.
Environments
We can deploy the same application multiple times in completely separated environments (also called “stages” by the Serverless CLI).
Bref Cloud
bref deploy --env=prod
# or
bref deploy -e prodThe default environment is dev. The example above deploys a prod environment.
Each environment is a separate CloudFormation stack, with completely separate AWS resources (Lambda functions, logs, permissions, etc.). All AWS resources are prefixed with the service and environment name (for example myapp-dev-api), which avoids any collision between environments.
It is possible to deploy different environments in different AWS accounts (to lock down permissions), and to deploy one environment per git branch, pull request, or even developer in the team.
Automating deployments
Bref Cloud
If you are using Bref Cloud , you can easily set up automatic deployments from CI/CD tools.
Read the documentation on deploying with Bref Cloud for more information.
Serverless CLI
If you are using GitHub Actions, GitLab CI, CircleCI, or any tool of the sort, you will want to automate the deployment to something like this:
# Install Composer dependencies optimized for production
composer install --prefer-dist --optimize-autoloader --no-dev
# Perform extra tasks for your framework of choice
# (e.g. generate the framework cache)
# [...]
# Deploy
serverless deployThe CI also needs AWS credentials to deploy. With GitHub Actions, the recommended way is to let the workflow assume an IAM role through OpenID Connect (OIDC), without storing AWS access keys:
- In your AWS account, create an IAM role that GitHub Actions can assume , with the permissions needed to deploy.
- Create a
.github/workflows/deploy.ymlworkflow:
name: Deploy
on:
push:
branches: [ main ]
permissions:
id-token: write # Required to assume the IAM role with OIDC
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
concurrency: deploy-prod # Avoid deploying concurrently
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: '24'
- run: npm install -g osls
# You can remove this step if you don't have a `package.json` file
- run: npm ci
- uses: shivammathur/setup-php@v2
with:
php-version: '8.4'
coverage: none
- uses: ramsey/composer-install@v4
with:
composer-options: '--optimize-autoloader --no-dev'
- uses: aws-actions/configure-aws-credentials@v6
with:
role-to-assume: arn:aws:iam::123456789012:role/github-actions-deploy
aws-region: us-east-1
- run: serverless deploy --stage=prodReplace the role ARN with the ARN of the role you created, and aws-region with the region of your application.
Other CI tools, like GitLab CI, also support OIDC with AWS. If yours doesn’t, create AWS access keys and set them in the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables of the CI job.
Regions
AWS runs applications in different regions . The default region is us-east-1 (North Virginia, USA).
If you want to use a different region (for example to host your application closer to your visitors) you can configure it in your serverless.yml:
provider:
region: eu-west-1 # Ireland, Europe
...If you are a first time user, using the us-east-1 region (the default region) is recommended for the first projects. It simplifies commands and avoids a lot of mistakes when discovering AWS.
Deletion
You can delete a deployed environment using the remove command.
Bref Cloud
bref remove
# or remove a specific environment
bref remove --env=prodBref Cloud will automatically delete the contents of AWS S3 buckets.
Secrets are kept in SSM Parameter Store under /<app>/<env>/, so that deploying the environment again reuses them (e.g. the same APP_KEY). To delete them too, use bref remove --delete-secrets, or check “Delete its secrets too” in the Bref Cloud dashboard.
Deleting an environment destroys the AWS resources that were created for that environment.
If you want to delete all environments of an application, you can do so in the Bref Cloud dashboard . If you don’t use Bref Cloud, you will need to delete each environment one by one.
How it works
CloudFormation stacks
Under the hood, Bref will deploy everything to AWS as a CloudFormation stack. A “stack” is nothing more than a bunch of things that compose an application:
- Lambda functions
- HTTP endpoints
- S3 buckets
- databases
- etc.
Stacks make it easy to group those resources together: the whole stack is updated at once on deployments, and if you delete the stack all the resources inside are deleted together too. Clean and simple.
Zero-downtime deployments
CloudFormation updates the Lambda functions without downtime: requests keep using the previous version of the code until the new version is deployed. If the deployment fails at any point, CloudFormation rolls it back and the previous version keeps running.
Asynchronous code
As soon as you introduce asynchronous behaviors (e.g. background jobs with SQS, event-driven microservices…) you may have in-flight messages (SQS jobs, EventBridge events…) created by the old version of your code that will be processed by the new version of your code.
Code that handles asynchronous events must be able to handle messages created by older versions of the code.
Database migrations
Zero-downtime deployments mean that database migrations must run when code is running in production. That means either before or after the deployment happens, and having a DB migration strategy compatible with that.
serverless.yml
Serverless Framework offers a simple configuration format. This is what you are using if you use Bref. That configuration is written in your project in a serverless.yml file.
You can learn more about that configuration format here.
Learn more
Read more about serverless deploy in the official documentation .