Deploy a Symfony application with AWS Lambda: in-depth analysis on advanced use

AlessandroMinoccheri
Flowing
Published in
5 min readDec 16, 2019

In the previous article, I’ve shown the deploy of a Symfony application on AWS Lambda.

Now I want to deep down on the deploy, talking about tmp folders and environment variables, explore how trigger deploy from events and show you some use case and scenarios.

Let’s start!

Symfony tweaks

Pay attention because AWS Lambda filesystem is in read-only mode, only the tmp folder is writable. So you need to move log, cache and uploaded files into some other places.

This is a cache example where I have checked the environment variable LAMBDA_TASK_ROOT to understand if the function is running on a Lambda service or not.
If the function is running on a Lambda service I have changed the path to store cache files.


//src/Kernel.php
public function getCacheDir(){ // When on the lambda only /tmp is writeable if (getenv(‘LAMBDA_TASK_ROOT’) !== false) { return ‘/tmp/cache/’.$this->environment; } return $this->getProjectDir().’/var/cache/’.$this->environment;}

For your logs you can write their directly on Cloudwatch service using a configuration like this:

# config/packages/prod/monolog.yamlmonolog:
handlers:
nested:
type: stream
path: 'php://stderr'

Upload example

We have talked about the upload file previously, with Symfony you can do it very easily with Lambda uploading file into S3Bucket.

Create a service with its environment variables:

acme.aws_s3.client:    public: true    class: Aws\S3\S3Client    factory: [Aws\S3\S3Client, ‘factory’]    arguments:    - version: latest    region: ‘%env(AWS_S3_REGION)%’    credentials:    key: ‘%env(AWS_S3_KEY)%’    secret: ‘%env(AWS_S3_SECRET)%’

Configure environment variables into serverless.yml file:

environment:    AWS_S3_REGION: ${ssm:/symfony-bref/AWS_S3_REGION:1}    AWS_S3_KEY: ${ssm:/symfony-bref/AWS_S3_KEY:1}    AWS_S3_SECRET: ${ssm:/symfony-bref/AWS_S3_SECRET:1}    AWS_S3_BUCKET_NAME: ${ssm:/symfony-bref/AWS_S3_BUCKET_NAME:1}

After that, you can create your service to upload a file on S3Bucket

public function upload(    S3Client $s3,    string $bucket,    string $contentType,    string $key,    string $path) {    $s3->putObject([        ‘Bucket’ => $bucket,        ‘Key’ => $key,        ‘SourceFile’ => $path,        ‘ContentType’ => $contentType    ]);}

An important thing to understand is that your files will be uploaded to an S3Bucket, but this bucket needs to be a new bucket because it’s important to separate code from uploaded files, because whenever you want you can destroy Lambda service and recreate it, in this case, if you’ll do it you can delete all uploaded files. With different buckets, you can destroy Lambda service when you want and uploaded files aren’t deleted.

Environment variables

Every application or function needs, usually, environment variables.

To use these environment variables for our Symfony Application into Lambda you can put those into serverless.yml file like this for example:

functions:    functionName:    environment:    MY_CUSTOM_ENV_VARIABLES: ‘…’

A best practice to follow is: don’t store secret values in serverless.yml directly.

You can store your secret values into SSM parameter store, a free service provided by AWS.

You can create manually the variable from the service or by the command-line interface with this command:

aws ssm put-parameter — region us-central -1 — name ‘/my-app/MY_CUSTOM_ENV_VARIABLES’ — type String — value ‘this is my custom env variables’

Now you can reference the variables into the serverless.yml file in this way:

AWS_ENV_VARIABLES: ${ssm:/my-app/my-parameter}

SSM parameter store is an AWS service shared for all your applications, so it’s recommended to prefix the parameter name with your application name.

Another AWS service similar to SSM parameter store is AWS Secrets Manager.

This service has these advantages:

- better permission management using IAM

- JSON values, allowing to store multiple values in one parameter

But remember that AWS Secrets Manager is not free.

Trigger from events

You can have a service to upload photos and you want to resize those, you can do it with an event that triggers your Lambda to resize photos.

If you want to trigger your code when an event is created you can add into your serverless.yaml file a little bit of configuration:

documents:    handler: public/index.php    events:        - s3:        bucket: photos        event: s3:ObjectCreated:*        rules:        - prefix: uploads/        - suffix: .jpg        - s3:        bucket: photos        event: s3:ObjectRemoved:*

In this case, you are listening for objects created events on the photos bucket with some rules:

- into the folder uploads

- with extension .jpg

When an event that respects those rules is created, automatically Lambda intercepts it and calls file public/index.php where you can do whatever you want: resize suddenly your photo or launch some other scripts to do it, in this case, it depends on your application.

Use cases and performance

The maturity of Bref and Aws Lambda with Symfony can open many scenarios of application that can use this stack, for example:

- APIs

- workers

- batch processes/scripts

- websites

As you can see all applications/services have very good performance.

But, before September 2019 it wasn’t like this.

Performance API with MySQL/PostgreSQL or website with MySQL/PostgreSQL isn’t so good because with these services you need to create a Lambda into a VPC that has cold starts of around 5 seconds.

The good news is gone out on 3 September 2019 from AWS that has announced an improvement of the VPC networking for AWS Lambda functions.

It means that now cold starts are removed, so all services with MySQL/PostgreSQL can have very good performance.

Jobs and cron are perfect candidates for a Lambda service because they are functions that are running sometimes. But there is a leak of integration with existing queue libraries, for that reason simplicity is orange.

Legacy applications have red points because usually, these projects are monoliths not designed for this type of architecture.

Why and when is recommended to use AWS Lambda

Why?

Using AWS Lambda has many advantages:

- It reduces costs

- It’s very safe

- No Infrastructure to manage, because AWS takes to care about it for you

- In 10 minutes or less, you have your application deployed from scratch

There are also many advantages but usually, it depends on your application.

When?

- When you have an independent service that needs to be called sometimes

- When you have a job, cron job to run sometimes

- When you have an API based system

- When you have websites

There are many and many cases to apply to a Lambda service since I have studied the concept of AWS Lambda, every time I look at a project I see Lambda everywhere, applicable in many points, services and concepts.

I hope this article helps you understand the power of Lambda services and how you can apply them to your projects. If you already have experience using Lambda with Symfony, I’d be curious to know what you think.

--

--