## Architecture
### Microservices
is defined when we separate different modules of an software stacks. Microservices have several benefits:
1. If one part fails, the whole program does not cease.
2. Only scale parts that need to scale.
3. The cost of updating/replacing is low since that codebase does not need to be coherent.
### Serverless
Essentially means you don't have to manage or provision resources for an application at all. These include:
- operating systems
- scalability
- availability
## Overview
Lambda is a server-less compute service in AWS. Lambda is a short-lived resource, limited by 15 minutes execution time. Although the default timeout is 3 seconds but it can be set to 15 minutes maximum.
Lambda is event-driven. It means the code **does not** run until something asks it to. Some include:
- API gateway: when a new API request is happened.
- Amazon Kinesis: when the transformed data needs transformation.
- Amazon DynamoDB: using Dynamo Streams, when a new write is done to a table.
- Amazon S3: when there is a S3 notification.
- Amazon SQS: when reading and processing a queue from SQS.
Lambda codes can be make from scratch, by using a blueprint, or by choosing a container image.
> [!important]
> An increase in the usage of Memory used by the Lambda function, will also proportionally inffcrease the allocated CPU and network bandwith.
### Concurrency
Concurrency in Lambda is the number of invocation that are currently being served. e.g. when 1000 users simultaneously do a web request.
Each invocation is running on its own container. The code of these invocations are running separately.
The term *maximum concurrent invocation* refers to the maximum number of invocations for a lambda function. The default number of this maximum is 1000, but can be changed.
*Reserved Concurrency* is when we partition the whole number concurrent invocation to certain Lambda functions.
#### Provisioned Concurrency
Since each invocations use its own container, the *init* phase of this bootstrap can cause a delay. However, AWS Lambda caches the execution environment and does a *hot start*.
But the cache only lasts for 1-10s. After that, Lambda should do a *cold start* instead.
![[Pasted image 20250219100635.png]]
Cold starts can be avoided by using *provisioned concurrency* that keeps a certain number of execution environment pre-initialised and ready for hot start.
The cost of provisioned concurrency is not low, especially for high number of pre-inited environments. AWS offers *provisioned concurrency autoscaling* that supports autoscaling based on usage. e.g. out of 100%, 20% are provisioned, 80% are in use.
> [!example]
> Reserved concurrency is like having *empty parking spots* reserved for cars to be on. Provisioned concurrency is like *having cars* in certain number of these spots ready to go whenever you want
Comparing different languages in cold-start delay, all but Java and .Net has similar effects. Python has amazingly have a low cold-start delay.
## Monitoring
The monitoring of a Lambda function is done in CloudTrail and CloudWatch.
In CloudWatch there exists a dashboard of shown number of invocations or number of failed instances.
In CloudTrail, the logs of each invocation can be seen for further troubleshooting. Also logs from different invocation can be joined and aggregated by AWS Log query.
> [!tip]
> By doing a Log query of a Lambda function, we can see how much memory it uses on average. This can help us to check if the lambda function is over-provisioned.
## Asynchronous Invocation
When a Lambda function is invoked, you wait for the function to process the event and return a response. However, with *[asynchronous invocation](https://docs.aws.amazon.com/lambda/latest/dg/invocation-async.html)*, Lambda **queue**s the event for processing and responses immediately.
![[Pasted image 20250219140838.png]]
The *downside* is that troubleshooting errors and logs can be harder with asynchronous invocation.
> [!tip]
> A Lambda function can automate AWS processes. e.g. it can stop EC2 instances in some hours to save money.
> However, it needs proper IAM roles.
## Best Practices
1. Keep-alive directive
2. Avoid Recursive Invocation
3. Write idempotent code
4. Separate Lambda Handler from Core Function Logic