SlideShare a Scribd company logo
1 of 56
Download to read offline
Less is more
Do more with less code in a serverless world
Jerome Van Der Linden
Geneva Serverless Meetup - 26/05/2020
About me
• In a previous life, ”Mr Cut Cut” (M. Coupe coupe)
• Developer & software craftsman
• And now, Solutions Architect @ AWS
2
linkedin.com/in/jeromevdl/
Jerome Van Der Linden
Few principles
Clean Code
SOLID
4
S Single Responsibility Principle
O Open / closed Principle
L Liskov substitution Principle
I Interface segregation Principle
D Dependency Inversion Principle
Single Responsibility Principle
5
“A class or module should have one,
and only one, reason to be changed”
- Robert C. Martin, aka Uncle Bob
YAGNI (You Ain’t Gonna Need It)
6
Just because you can,
doesn’t mean you should…
KISS
7
8
And many more…
Clean Code
DRY
Don’t Repeat Yourself
Law of Demeter
Broken window
theory
Boy scout rule
Not invented here
How to apply those principles?
In the serverless world
Serverless World?
10
Serverless == FAASFunction As A Service
Serverless World?
11
Serverless ⊃ FAASFunction As A Service
AWS Serverless world
12
AWS
Lambda
AWS
Fargate
Amazon
API Gateway
Amazon
SNS
Amazon
SQS
COMPUTE
DATA STORES
INTEGRATION
Amazon Aurora
Serverless
Amazon
S3
Amazon
DynamoDB
Amazon
EventBridge
FAAS
AWS
Step Functions
AWS
AppSync
Single Responsibility Principle
ü Do’s ✘ Don’ts *
- Input validation
- Business logic /!
- Transform data
- Return result
- Event/Input Filtering
- Transport data
- Orchestration & long
transactions
- Retry/Failure handling
* Most of the time
Event Filtering
15
SNS
Topic
Publisher
if event_type == 'order_created’:
lambda_client.invoke('OrderCreation', ...)
elif event_type == 'order_placed’:
lambda_client.invoke('OrderPlacement', ...)
elif event_type == 'order_cancelled’:
lambda_client.invoke('OrderCancelation', ...)
OrderCreation
OrderPlacement
OrderCancellation
{
"event_type": "order_placed",
"order": {
"id": "232134",
"amount": "2341,45",
"stock_ref": "AMZN”
}
}
the wrong way
𝝺 function code
Input event
OrderFiltering
Event Filtering with SNS
16
OrderCreation
OrderPlacement
OrderCancellation
Publisher
OrderCreationEvent:
Type: AWS::SNS::Subscription
Properties:
TopicArn: 'arn:aws:sns:eu-central-1:123456789:OrdersTopic’
Protocol: lambda
Endpoint: 'arn:aws:lambda:eu-central-1:123456789:function:OrderCreation’
FilterPolicy:
event_type:
- order_created
SNS
Topic
https://docs.aws.amazon.com/sns/latest/dg/sns-subscription-filter-policies.html
Cloudformation template
{
"event_type": [
"order_created"
]
}
Filter policy
Event Filtering with SNS
17
OrderCreation
OrderPlacement
OrderCancellation
Publisher
OrderPlacementEvent:
Type: AWS::SNS::Subscription
Properties:
TopicArn: 'arn:aws:sns:eu-central-1:123456789:OrdersTopic’
Protocol: lambda
Endpoint: 'arn:aws:lambda:eu-central-1:123456789:function:OrderPlacement’
FilterPolicy:
event_type:
- order_placed
SNS
Topic
Cloudformation template
Event Filtering with SNS
18
OrderCreation
OrderPlacement
OrderCancellation
Publisher
OrderCancellationEvent:
Type: AWS::SNS::Subscription
Properties:
TopicArn: 'arn:aws:sns:eu-central-1:123456789:OrdersTopic’
Protocol: lambda
Endpoint: 'arn:aws:lambda:eu-central-1:123456789:function:OrderCancellation’
FilterPolicy:
event_type:
- order_cancelled
SNS
Topic
Cloudformation template
Event Filtering with EventBridge
19
https://aws.amazon.com/blogs/compute/reducing-custom-code-by-using-advanced-rules-in-amazon-eventbridge/
{
"Source": "custom.myATMapp",
"EventBusName": "default",
"DetailType": "transaction",
"Time": "Wed Jan 29 2020 08:03:18 GMT-0500",
"Detail":{
"action": "withdrawal",
"location": "NY-NYC-001",
"amount": 300,
"result": "approved",
"transactionId": "123456",
"cardPresent": true,
"partnerBank": "Example Bank",
"remainingFunds": 722.34
}
}
{
"source": [ "custom.myATMapp" ],
"detail-type": [ "transaction" ],
"detail": {
"amount": [ { "numeric": [ ">", 300 ] } ]
}
}
{
"source": [ "custom.myATMapp" ],
"detail-type": [ "transaction" ],
"detail": {
"location": [ { "prefix": "NY-NYC-" } ]
}
}
{
"source": [ "custom.myATMapp" ],
"detail-type": [ "transaction" ],
"detail": {
"partnerBank": [ { "exists": true } ]
}
}
{
"source": [ "custom.myATMapp" ],
"detail-type": [ "transaction" ],
"detail": {
"result": [ "approved" ],
"partnerBank": [ { "exists": false } ],
"location": [ { "anything-but": "NY-NYC-002" }]
}
}
Orchestration
20
the wrong way
invoke
invokeif (…
)
invoke //
else
if (success)
Notify with SNS
n * invoke
if (failure)
Enqueue error
notify with SNS
need approval
App…
Simple orchestration with Lambda destinations
21
invoke
invokeif (…
)
invoke //
else
if (success)
Notify with SNS
n * invoke
if (failure)
Enqueue error
notify with SNS
need approval
App…
Lambda Destinations
Simple orchestration with Lambda destinations
22
Amazon SNS
Amazon
EventBridge
Amazon
Cloudwatch Logs
Amazon S3
Amazon SES
AWS Config
Amazon
CloudFormation
AWS
CodeCommit
A
S
Y
N
C
"DestinationConfig": {
"onSuccess": {
"Destination": "arn:aws:lambda:..."
},
"onFailure": {
"Destination": "arn:aws:sqs:..."
}
}
Cloudformation template
Amazon SNS
Amazon
EventBridge
Amazon
SQS
AWS Lambda
if success:
return {...}
else:
raise Exception(‘Failure', {...})
𝝺 function code
Lambda function
A
S
Y
N
C
Advanced orchestration with Step Functions
23
invoke
invokeif (…
)
invoke //
else
if (success)
Notify with SNS
n * invoke
if (failure)
Enqueue error
notify with SNS
need approval
App…
Advanced orchestration with Step Functions
24
invoke
invokeif (…
)
invoke //
else
if (success)
Notify with SNS
n * invoke
if (failure)
Enqueue error
notify with SNS
need approval
App…
{
"StartAt": "SimpleInvocation",
"States": {
"SimpleInvocation": {
"Type": "Task",
"Resource": "arn:aws:lambda:eu-central-
1:123456789012:function:HelloFunction",
"Next": "Choose1or2"
},
Advanced orchestration with Step Functions
25
invoke
invokeif (…
)
invoke //
else
if (success)
Notify with SNS
n * invoke
if (failure)
Enqueue error
notify with SNS
need approval
App…
"Choose1or2": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.foo”,
"NumericEquals": 1,
"Next": "Lambda1"
},
{
"Variable": "$.foo",
"NumericEquals": 2,
"Next": "ParallelInvocation"
}
],
"Default": "Unmatched"
},
Advanced orchestration with Step Functions
26
invoke
invokeif (…
)
invoke //
else
if (success)
Notify with SNS
n * invoke
if (failure)
Enqueue error
notify with SNS
need approval
App…
"Lambda1": {
"Type": "Task",
"Resource": "arn:aws:lambda:eu-
central-1:123456789012:function:Lambda1",
"Next": "SuccessOrFailure"
},
Advanced orchestration with Step Functions
27
invoke
invokeif (…
)
invoke //
else
if (success)
Notify with SNS
n * invoke
if (failure)
Enqueue error
notify with SNS
need approval
App…
"SuccessOrFailure": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.status",
"StringEquals": "SUCCESS",
"Next": "SendNotification"
},
{
"Variable": "$.status",
"StringEquals": "FAILURE",
"Next": "QueueError"
}
],
"Default": "Unmatched"
}
Advanced orchestration with Step Functions
28
invoke
invokeif (…
)
invoke //
else
if (success)
Notify with SNS
n * invoke
if (failure)
Enqueue error
notify with SNS
need approval
App…
"SendNotification": {
"Type": "Succeed"
},
"QueueError": {
"Type": "Fail"
},
Advanced orchestration with Step Functions
29
invoke
invokeif (…
)
invoke //
else
if (success)
Notify with SNS
n * invoke
if (failure)
Enqueue error
notify with SNS
need approval
App…
"ParallelInvocation": {
"Type": "Parallel",
"Branches": [
{
"StartAt": "SendApprovalRequest",
"States": {
"SendApprovalRequest": {
// ...
}
},
{
"StartAt": "Loop",
"States": {
"Loop": {
// ...
}
}
}
Advanced orchestration with Step Functions
30
invoke
invokeif (…
)
invoke //
else
if (success)
Notify with SNS
n * invoke
if (failure)
Enqueue error
notify with SNS
need approval
App…
"SendApprovalRequest": {
"Type": "Task",
"Resource":
"arn:aws:states:::lambda:invoke.waitForTaskToken",
"Parameters": {
"FunctionName": "sendMailForApprovalFunction",
"Payload": {
"step.$": "$$.State.Name",
"model.$": "$.data",
"token.$": "$$.Task.Token"
}
},
"ResultPath": "$.output",
"Next": "Approved",
"Catch": [
{
"ErrorEquals": [ "rejected" ],
"ResultPath": "$.reason",
"Next": "Rejected"
}
]
}
SendTaskSuccess
SendTaskFailure
Advanced orchestration with Step Functions
31
invoke
invokeif (…
)
invoke //
else
if (success)
Notify with SNS
n * invoke
if (failure)
Enqueue error
notify with SNS
need approval
App…
"Loop": {
"Type": "Map",
"ItemsPath": "$.loopItems",
"Iterator": {
"StartAt": "LoopLambda",
"States": {
"LoopLambda": {
"Type": "Task",
"Resource": "arn:aws:lambda:us-east-
1:123456789012:function:LoopFunction",
"End": true
}
}
},
"End": true
}
Advanced orchestration with Step Functions
32
invoke
invokeif (…
)
invoke //
else
if (success)
Notify with SNS
n * invoke
if (failure)
Enqueue error
notify with SNS
need approval
App…
TL;DR Single Responsibility Principle
33
èKeep your 𝝺 code focused on the business
This is not the responsibility of a 𝝺 to do orchestration
You ain’t gonna need it
34
Welcome in the “functionless” world !
API Gateway Service Proxy
35
Ex: insert data in DynamoDB
36
Resource: /comments
HTTP Method: POST
HTTP Request Body: {
"pageId": "example-page-id",
"userName": "ExampleUserName",
"message": "Example comment to be added."
}
Table: Comments
commentId: String
userName: String
message: String
pageId: String
PK: commentIdAPI Gateway DynamoDBLambda
var AWS = require('aws-sdk');
var ddb = new AWS.DynamoDB({apiVersion: '2012-08-10'});
exports.handler = async function(event, context) {
var params = {
TableName: 'Comments’,
Item: {
'commentId' : {
S: 'randomid’
},
'pageId' : {
S: event.pageId
},
'userName' : {
S: event.userName
},
'message' : {
S: event.message
}
}
};
ddb.putItem(params, function(err, data) {
if (err) {
console.log("Error", err);
} else {
console.log("Success", data);
}
});
}
Ex: insert data in DynamoDB
37
Resource: /comments
HTTP Method: POST
HTTP Request Body: {
"pageId": "example-page-id",
"userName": "ExampleUserName",
"message": "Example comment to be added."
}
Table: Comments
commentId: String
userName: String
message: String
pageId: String
PK: commentIdAPI Gateway DynamoDB
Ex: insert data in DynamoDB
38
Resource: /comments
HTTP Method: POST
HTTP Request Body: {
"pageId": "example-page-id",
"userName": "ExampleUserName",
"message": "Example comment to be added."
}
Table: Comments
commentId: String
userName: String
message: String
pageId: String
PK: commentIdAPI Gateway DynamoDB
Ex: insert data in DynamoDB
39
Resource: /comments
HTTP Method: POST
HTTP Request Body: {
"pageId": "example-page-id",
"userName": "ExampleUserName",
"message": "Example comment to be added."
}
Table: Comments
commentId: String
userName: String
message: String
pageId: String
PK: commentIdAPI Gateway DynamoDB
Ex: insert data in DynamoDB
40
Resource: /comments
HTTP Method: POST
HTTP Request Body: {
"pageId": "example-page-id",
"userName": "ExampleUserName",
"message": "Example comment to be added."
}
Table: Comments
commentId: String
userName: String
message: String
pageId: String
PK: commentIdAPI Gateway DynamoDB
Ex: insert data in DynamoDB
41
Resource: /comments
HTTP Method: POST
HTTP Request Body: {
"pageId": "example-page-id",
"userName": "ExampleUserName",
"message": "Example comment to be added."
}
Table: Comments
commentId: String
userName: String
message: String
pageId: String
PK: commentIdAPI Gateway DynamoDB
Use with caution
42
• Not a generic design pattern, not
always applicable
• Apply when the lambda is a
passthrough (no business code, just
mapping)
• Mapping can sometimes be complex
(Velocity Template Language)
Step Function integrations
43
"QueueError": {
"Type": "Task",
"Resource": "arn:aws:states:::sqs:sendMessage",
"Parameters": {
"QueueUrl": "https://sqs.eu-central-1.amazonaws.com/123456789012/myQueue",
"MessageBody.$": "$.input.message"
},
"End": true
},
"SendNotification": {
"Type": "Task",
"Resource": "arn:aws:states:::sns:publish",
"Parameters": {
"TopicARN": "arn:aws:sns:eu-central-
1:123456789012:myTopic",
"Subject": "Lambda1 has successfully finish its job",
"Message.$" : "$.input.message"
},
"End": true
},
SQS
SNS
Step Function integrations
44
AWS Batch Amazon DynamoDB Amazon ECS / Fargate Amazon EMR AWS Glue
Amazon SageMaker Amazon SNS Amazon SQS AWS Step Functions
AWS Lambda
AWS CodeBuild
TL;DR You Ain’t Gonna Need It
45
è 𝝺 is not always needed
You can save costs and
optimize performance
when functions are just passthrough/mapping
Keep it simple stupid
46
Lighten your functions
Keep your functions simple & stupid
nano functions
API GW
/res1
/res2
/res3
= 1 handler (1 function)
= 1 file
Not that stupid
so they need
sisters to do the job !
Keep your functions simple & stupid
nano functions
API GW
/res1
/res2
/res3
= 1 handler (1 function)
= 1 file
function-lith
API GW
/{proxy}
/res1
/res2
/res3
That’s really not simple & stupid!
= 1 handler (1 function)
= 1 file
Keep your functions simple & stupid
nano functions
API GW
/res1
/res2
/res3
function-lith
API GW
/{proxy}
/res1
/res2
/res3
= 1 handler (1 function)
= 1 file
fat functions
API GW
/res1
/res2
/res3
= 3 handlers (3 functions)
= 1 file
= 1 handler (1 function)
= 1 file
Keep your functions simple & stupid
50
nano functions
API GW
/res1
/res2
/res3
function-lith
API GW
/{proxy}
/res1
/res2
/res3
fat functions
= 1 handler (1 function)
= 1 file
API GW
= 3 handler (3 functions)
= 1 file
micro functions
API GW
/res1
/res2
/res3
/res1
/res2
/res3
= 1 handler (1 function)
= 1 file
= 1 handler (1 function)
= 1 file
Keep your functions simple & stupid
https://github.com/cdk-patterns/serverless/tree/master/the-lambda-trilogy
Potential duplicated code ++
Cognitive burden ++
Coupled functions
Coupled deployments
nano functions
API GW
/res1
/res2
/res3
function-lith
API GW
/{proxy}
/res1
/res2
/res3
fat functions
= 1 handler (1 function)
= 1 file
API GW
= 3 handler (3 functions)
= 1 file
micro functions
/res1
/res2
/res3
= 1 handler (1 function)
= 1 file
API GW
/res1
/res2
/res3
= 1 handler (1 function)
= 1 file
Stupidity Complexity
FAAS?
Longer cold starts ++
Risk of blast radius
Framework dependent
Longer cold starts
Risk of blast radius
Potential duplicated code
Cognitive burden
TL;DR Keep it simple stupid
52
Lighter functions
=
Easier to test and maintain
Faster to start: less cold start
More scalable: higher throughput
More secure: less permission needed
Conclusion
No function is easier to manage
than ‘no function’
– me
è If you can do better without a
function, just do it
è Else, apply software
craftsmanship principles
(clean code, tests, code reviews…)
“No server is easier to
manage than ‘no server’”
– Werner Vogels
Thank You @jeromevdl
https://tinyurl.com/ydeowzut
2-minutes survey:
Appendix
AWSTemplateFormatVersion: 2010-09-09
Resources:
API:
Type: AWS::ApiGateway::RestApi
Properties:
Name: !Sub ${AWS::StackName}-api-
${AWS::AccountId}
APIDeployment:
Type: AWS::ApiGateway::Deployment
Properties:
RestApiId: !Ref API
StageName: prod
DependsOn:
- ListBucketAPI
APIBucketResource:
Type: AWS::ApiGateway::Resource
Properties:
ParentId: !GetAtt API.RootResourceId
PathPart: "{bucket}"
RestApiId: !Ref API
ListBucketAPI:
Type: AWS::ApiGateway::Method
Properties:
HttpMethod: GET
ResourceId: !Ref APIBucketResource
RestApiId: !Ref API
AuthorizationType: NONE
Integration:
Credentials: 'arn:aws:iam::1234567890:role/role-demo-api-gw-s3-integration’
IntegrationHttpMethod: GET
IntegrationResponses:
- StatusCode: "200"
PassthroughBehavior: WHEN_NO_MATCH
RequestParameters:
integration.request.header.Content-Type: method.request.header.Content-Type
integration.request.header.x-amz-acl: "'authenticated-read’”
integration.request.path.bucket: method.request.path.bucket
Type: AWS
Uri: !Sub arn:aws:apigateway:${AWS::Region}:s3:path/{bucket}
MethodResponses:
- StatusCode: "200"
RequestParameters:
method.request.path.bucket: true
method.request.header.Content-Type: false
API Gateway & S3 sample
https://docs.aws.amazon.com/apigateway/latest/developerguide/integrating-api-with-aws-services-s3.html
57
Advanced orchestration with Step Functions{
"StartAt": "SimpleInvocation",
"States": {
"SimpleInvocation": {
"Type": "Task",
"Resource": "arn:aws:lambda:eu-central-1:123456789012:function:HelloFunction",
"Next": "Choose1or2"
},
"Choose1or2": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.foo",
"NumericEquals": 1,
"Next": "Lambda1"
},
{
"Variable": "$.foo",
"NumericEquals": 2,
"Next": "ParallelInvocation"
}
],
"Default": "Unmatched"
},
"Lambda1": {
"Type": "Task",
"Resource": "arn:aws:lambda:eu-central-1:123456789012:function:Lambda1",
"Next": "SuccessOrFailure"
},
"SuccessOrFailure": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.status",
"StringEquals": "SUCCESS",
"Next": "SendNotification"
},
{
"Variable": "$.status",
"StringEquals": "FAILURE",
"Next": "QueueError"
}
],
"Default": "Unmatched"
},
"SendNotification": {
"Type": "Succeed"
},
"QueueError": {
"Type": "Fail"
},
"ParallelInvocation": {
"Type": "Parallel",
"Branches": [
{
"StartAt": "SendApprovalRequest",
"States": {
"SendApprovalRequest": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke.waitForTaskToken",
"Parameters": {
"FunctionName": "sendMailForApprovalFunction",
"Payload": {
"step.$": "$$.State.Name",
"model.$": "$.data",
"token.$": "$$.Task.Token"
}
},
"ResultPath": "$.output",
"Next": "Approved",
"Catch": [
{
"ErrorEquals": [ "rejected" ],
"ResultPath": "$.reason",
"Next": "Rejected"
}
]
},
"Approved": {
"Type": "Task",
"Resource": "arn:aws:lambda:eu-central-1:123456789012:function:Lambda1",
"End": true
},
"Rejected": {
"Type": "Fail"
}
}
},
{
"StartAt": "Loop",
"States": {
"Loop": {
"Type": "Map",
"ItemsPath": "$.loopItems",
"Iterator": {
"StartAt": "LoopLambda",
"States": {
"LoopLambda": {
"Type": "Task",
"Resource": "arn:aws:lambda:us-east-1:123456789012:function:LoopFunction",
"End": true
}
}
},
"End": true
}
}
}
],
"End": true
},
"Unmatched": {
"Type": "Fail",
"Error": "DefaultStateError",
"Cause": "No Matches!"
}
}
}

More Related Content

What's hot

Building @Anywhere (for TXJS)
Building @Anywhere (for TXJS)Building @Anywhere (for TXJS)
Building @Anywhere (for TXJS)danwrong
 
Non Conventional Android Programming En
Non Conventional Android Programming EnNon Conventional Android Programming En
Non Conventional Android Programming Enguest9bcef2f
 
Zend server 6 using zf2, 2013 webinar
Zend server 6 using zf2, 2013 webinarZend server 6 using zf2, 2013 webinar
Zend server 6 using zf2, 2013 webinarYonni Mendes
 
James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...
James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...
James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...Codemotion
 
Elixir Paris Meetup
Elixir Paris MeetupElixir Paris Meetup
Elixir Paris MeetupJoan Zapata
 
The promise of asynchronous php
The promise of asynchronous phpThe promise of asynchronous php
The promise of asynchronous phpWim Godden
 
UA testing with Selenium and PHPUnit - PHPBenelux Summer BBQ
UA testing with Selenium and PHPUnit - PHPBenelux Summer BBQUA testing with Selenium and PHPUnit - PHPBenelux Summer BBQ
UA testing with Selenium and PHPUnit - PHPBenelux Summer BBQMichelangelo van Dam
 
Natural Task Scheduling Using Futures and Continuations, Ivan Čukić, Qt Devel...
Natural Task Scheduling Using Futures and Continuations, Ivan Čukić, Qt Devel...Natural Task Scheduling Using Futures and Continuations, Ivan Čukić, Qt Devel...
Natural Task Scheduling Using Futures and Continuations, Ivan Čukić, Qt Devel...Ivan Čukić
 
Bhanu Pratap Singh Shekhawat, BCA Third Year
Bhanu Pratap Singh Shekhawat, BCA Third YearBhanu Pratap Singh Shekhawat, BCA Third Year
Bhanu Pratap Singh Shekhawat, BCA Third YearDezyneecole
 
the 5 layers of web accessibility - Open Web Camp II
the 5 layers of web accessibility - Open Web Camp IIthe 5 layers of web accessibility - Open Web Camp II
the 5 layers of web accessibility - Open Web Camp IIDirk Ginader
 
Fórum de Software Livre do Serpro RJ 2009
Fórum de Software Livre do Serpro RJ 2009Fórum de Software Livre do Serpro RJ 2009
Fórum de Software Livre do Serpro RJ 2009Fabio Akita
 
2013-06-25 - HTML5 & JavaScript Security
2013-06-25 - HTML5 & JavaScript Security2013-06-25 - HTML5 & JavaScript Security
2013-06-25 - HTML5 & JavaScript SecurityJohannes Hoppe
 
AngularJS with TypeScript and Windows Azure Mobile Services
AngularJS with TypeScript and Windows Azure Mobile ServicesAngularJS with TypeScript and Windows Azure Mobile Services
AngularJS with TypeScript and Windows Azure Mobile ServicesRainer Stropek
 
GDayX - Advanced Angular.JS
GDayX - Advanced Angular.JSGDayX - Advanced Angular.JS
GDayX - Advanced Angular.JSNicolas Embleton
 
AngularJS Animations
AngularJS AnimationsAngularJS Animations
AngularJS AnimationsEyal Vardi
 
Vue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMRVue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMRJavier Abadía
 
HTML5 Web Messaging
HTML5 Web MessagingHTML5 Web Messaging
HTML5 Web MessagingMike Taylor
 

What's hot (19)

Building @Anywhere (for TXJS)
Building @Anywhere (for TXJS)Building @Anywhere (for TXJS)
Building @Anywhere (for TXJS)
 
Non Conventional Android Programming En
Non Conventional Android Programming EnNon Conventional Android Programming En
Non Conventional Android Programming En
 
Zend server 6 using zf2, 2013 webinar
Zend server 6 using zf2, 2013 webinarZend server 6 using zf2, 2013 webinar
Zend server 6 using zf2, 2013 webinar
 
Micro app-framework
Micro app-frameworkMicro app-framework
Micro app-framework
 
James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...
James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...
James Thomas - Serverless Machine Learning With TensorFlow - Codemotion Berli...
 
Prototype UI
Prototype UIPrototype UI
Prototype UI
 
Elixir Paris Meetup
Elixir Paris MeetupElixir Paris Meetup
Elixir Paris Meetup
 
The promise of asynchronous php
The promise of asynchronous phpThe promise of asynchronous php
The promise of asynchronous php
 
UA testing with Selenium and PHPUnit - PHPBenelux Summer BBQ
UA testing with Selenium and PHPUnit - PHPBenelux Summer BBQUA testing with Selenium and PHPUnit - PHPBenelux Summer BBQ
UA testing with Selenium and PHPUnit - PHPBenelux Summer BBQ
 
Natural Task Scheduling Using Futures and Continuations, Ivan Čukić, Qt Devel...
Natural Task Scheduling Using Futures and Continuations, Ivan Čukić, Qt Devel...Natural Task Scheduling Using Futures and Continuations, Ivan Čukić, Qt Devel...
Natural Task Scheduling Using Futures and Continuations, Ivan Čukić, Qt Devel...
 
Bhanu Pratap Singh Shekhawat, BCA Third Year
Bhanu Pratap Singh Shekhawat, BCA Third YearBhanu Pratap Singh Shekhawat, BCA Third Year
Bhanu Pratap Singh Shekhawat, BCA Third Year
 
the 5 layers of web accessibility - Open Web Camp II
the 5 layers of web accessibility - Open Web Camp IIthe 5 layers of web accessibility - Open Web Camp II
the 5 layers of web accessibility - Open Web Camp II
 
Fórum de Software Livre do Serpro RJ 2009
Fórum de Software Livre do Serpro RJ 2009Fórum de Software Livre do Serpro RJ 2009
Fórum de Software Livre do Serpro RJ 2009
 
2013-06-25 - HTML5 & JavaScript Security
2013-06-25 - HTML5 & JavaScript Security2013-06-25 - HTML5 & JavaScript Security
2013-06-25 - HTML5 & JavaScript Security
 
AngularJS with TypeScript and Windows Azure Mobile Services
AngularJS with TypeScript and Windows Azure Mobile ServicesAngularJS with TypeScript and Windows Azure Mobile Services
AngularJS with TypeScript and Windows Azure Mobile Services
 
GDayX - Advanced Angular.JS
GDayX - Advanced Angular.JSGDayX - Advanced Angular.JS
GDayX - Advanced Angular.JS
 
AngularJS Animations
AngularJS AnimationsAngularJS Animations
AngularJS Animations
 
Vue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMRVue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMR
 
HTML5 Web Messaging
HTML5 Web MessagingHTML5 Web Messaging
HTML5 Web Messaging
 

Similar to Do more with less code in a serverless world

Building Awesome API with Spring
Building Awesome API with SpringBuilding Awesome API with Spring
Building Awesome API with SpringVladimir Tsukur
 
Intravert Server side processing for Cassandra
Intravert Server side processing for CassandraIntravert Server side processing for Cassandra
Intravert Server side processing for CassandraEdward Capriolo
 
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"DataStax Academy
 
Monitoring Your ISP Using InfluxDB Cloud and Raspberry Pi
Monitoring Your ISP Using InfluxDB Cloud and Raspberry PiMonitoring Your ISP Using InfluxDB Cloud and Raspberry Pi
Monitoring Your ISP Using InfluxDB Cloud and Raspberry PiInfluxData
 
Do more with less code in serverless
Do more with less code in serverlessDo more with less code in serverless
Do more with less code in serverlessjeromevdl
 
Clean Code Development
Clean Code DevelopmentClean Code Development
Clean Code DevelopmentPeter Gfader
 
Deliver Business Value Faster with AWS Step Functions
Deliver Business Value Faster with AWS Step FunctionsDeliver Business Value Faster with AWS Step Functions
Deliver Business Value Faster with AWS Step FunctionsDaniel Zivkovic
 
How to ship customer value faster with step functions
How to ship customer value faster with step functionsHow to ship customer value faster with step functions
How to ship customer value faster with step functionsYan Cui
 
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and JasmineRails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and JasmineRaimonds Simanovskis
 
Stuff I Learned About Performance
Stuff I Learned About PerformanceStuff I Learned About Performance
Stuff I Learned About PerformanceMichael Barker
 
Delightful steps to becoming a functioning user of Step Functions
Delightful steps to becoming a functioning user of Step FunctionsDelightful steps to becoming a functioning user of Step Functions
Delightful steps to becoming a functioning user of Step FunctionsYan Cui
 
Surviving javascript.pptx
Surviving javascript.pptxSurviving javascript.pptx
Surviving javascript.pptxTamas Rev
 
Serverless Swift with Apache OpenWhisk. UA Mobile 2017.
Serverless Swift with Apache OpenWhisk. UA Mobile 2017.Serverless Swift with Apache OpenWhisk. UA Mobile 2017.
Serverless Swift with Apache OpenWhisk. UA Mobile 2017.UA Mobile
 
.NET Foundation, Future of .NET and C#
.NET Foundation, Future of .NET and C#.NET Foundation, Future of .NET and C#
.NET Foundation, Future of .NET and C#Bertrand Le Roy
 
Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)Scott Wlaschin
 
E.D.D.I - Open Source Chatbot Platform
E.D.D.I - Open Source Chatbot PlatformE.D.D.I - Open Source Chatbot Platform
E.D.D.I - Open Source Chatbot PlatformGregor Jarisch
 
Real-time search in Drupal with Elasticsearch @Moldcamp
Real-time search in Drupal with Elasticsearch @MoldcampReal-time search in Drupal with Elasticsearch @Moldcamp
Real-time search in Drupal with Elasticsearch @MoldcampAlexei Gorobets
 
A miało być tak... bez wycieków
A miało być tak... bez wyciekówA miało być tak... bez wycieków
A miało być tak... bez wyciekówKonrad Kokosa
 

Similar to Do more with less code in a serverless world (20)

Building Awesome API with Spring
Building Awesome API with SpringBuilding Awesome API with Spring
Building Awesome API with Spring
 
Intravert Server side processing for Cassandra
Intravert Server side processing for CassandraIntravert Server side processing for Cassandra
Intravert Server side processing for Cassandra
 
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
 
Monitoring Your ISP Using InfluxDB Cloud and Raspberry Pi
Monitoring Your ISP Using InfluxDB Cloud and Raspberry PiMonitoring Your ISP Using InfluxDB Cloud and Raspberry Pi
Monitoring Your ISP Using InfluxDB Cloud and Raspberry Pi
 
Do more with less code in serverless
Do more with less code in serverlessDo more with less code in serverless
Do more with less code in serverless
 
Clean Code Development
Clean Code DevelopmentClean Code Development
Clean Code Development
 
Deliver Business Value Faster with AWS Step Functions
Deliver Business Value Faster with AWS Step FunctionsDeliver Business Value Faster with AWS Step Functions
Deliver Business Value Faster with AWS Step Functions
 
How to ship customer value faster with step functions
How to ship customer value faster with step functionsHow to ship customer value faster with step functions
How to ship customer value faster with step functions
 
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and JasmineRails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
 
Stuff I Learned About Performance
Stuff I Learned About PerformanceStuff I Learned About Performance
Stuff I Learned About Performance
 
Health Monitoring
Health MonitoringHealth Monitoring
Health Monitoring
 
Delightful steps to becoming a functioning user of Step Functions
Delightful steps to becoming a functioning user of Step FunctionsDelightful steps to becoming a functioning user of Step Functions
Delightful steps to becoming a functioning user of Step Functions
 
Surviving javascript.pptx
Surviving javascript.pptxSurviving javascript.pptx
Surviving javascript.pptx
 
Serverless Swift with Apache OpenWhisk. UA Mobile 2017.
Serverless Swift with Apache OpenWhisk. UA Mobile 2017.Serverless Swift with Apache OpenWhisk. UA Mobile 2017.
Serverless Swift with Apache OpenWhisk. UA Mobile 2017.
 
Webauthn Tutorial
Webauthn TutorialWebauthn Tutorial
Webauthn Tutorial
 
.NET Foundation, Future of .NET and C#
.NET Foundation, Future of .NET and C#.NET Foundation, Future of .NET and C#
.NET Foundation, Future of .NET and C#
 
Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)
 
E.D.D.I - Open Source Chatbot Platform
E.D.D.I - Open Source Chatbot PlatformE.D.D.I - Open Source Chatbot Platform
E.D.D.I - Open Source Chatbot Platform
 
Real-time search in Drupal with Elasticsearch @Moldcamp
Real-time search in Drupal with Elasticsearch @MoldcampReal-time search in Drupal with Elasticsearch @Moldcamp
Real-time search in Drupal with Elasticsearch @Moldcamp
 
A miało być tak... bez wycieków
A miało być tak... bez wyciekówA miało być tak... bez wycieków
A miało być tak... bez wycieków
 

More from jeromevdl

Message-Driven Architecture on AWS
Message-Driven Architecture on AWSMessage-Driven Architecture on AWS
Message-Driven Architecture on AWSjeromevdl
 
DevopsDays Geneva 2020 - Compliance & Governance as Code
DevopsDays Geneva 2020 - Compliance & Governance as CodeDevopsDays Geneva 2020 - Compliance & Governance as Code
DevopsDays Geneva 2020 - Compliance & Governance as Codejeromevdl
 
Softshake 2017 - Développer un chatbot Alexa
Softshake 2017 - Développer un chatbot AlexaSoftshake 2017 - Développer un chatbot Alexa
Softshake 2017 - Développer un chatbot Alexajeromevdl
 
Chatbots buzzword ou nouvel eldorado
Chatbots   buzzword ou nouvel eldoradoChatbots   buzzword ou nouvel eldorado
Chatbots buzzword ou nouvel eldoradojeromevdl
 
Management projet vs management produit
Management projet vs management produitManagement projet vs management produit
Management projet vs management produitjeromevdl
 
Softshake - Offline applications
Softshake - Offline applicationsSoftshake - Offline applications
Softshake - Offline applicationsjeromevdl
 
My Android is not an iPhone like any others (Mdevcon 2014)
My Android is not an iPhone like any others (Mdevcon 2014)My Android is not an iPhone like any others (Mdevcon 2014)
My Android is not an iPhone like any others (Mdevcon 2014)jeromevdl
 
DroidconUK 2013 : Beef up android apps with java tools
DroidconUK 2013 : Beef up android apps with java toolsDroidconUK 2013 : Beef up android apps with java tools
DroidconUK 2013 : Beef up android apps with java toolsjeromevdl
 
Droidcon Paris 2013 - Musclez vos applications Android avec les outils du mon...
Droidcon Paris 2013 - Musclez vos applications Android avec les outils du mon...Droidcon Paris 2013 - Musclez vos applications Android avec les outils du mon...
Droidcon Paris 2013 - Musclez vos applications Android avec les outils du mon...jeromevdl
 
Devoxx France 2013 : Musclez vos apps android avec les outils du monde java
Devoxx France 2013 : Musclez vos apps android avec les outils du monde javaDevoxx France 2013 : Musclez vos apps android avec les outils du monde java
Devoxx France 2013 : Musclez vos apps android avec les outils du monde javajeromevdl
 
Jug Lausanne Android Janvier2013
Jug Lausanne Android Janvier2013Jug Lausanne Android Janvier2013
Jug Lausanne Android Janvier2013jeromevdl
 

More from jeromevdl (12)

Message-Driven Architecture on AWS
Message-Driven Architecture on AWSMessage-Driven Architecture on AWS
Message-Driven Architecture on AWS
 
DevopsDays Geneva 2020 - Compliance & Governance as Code
DevopsDays Geneva 2020 - Compliance & Governance as CodeDevopsDays Geneva 2020 - Compliance & Governance as Code
DevopsDays Geneva 2020 - Compliance & Governance as Code
 
Softshake 2017 - Développer un chatbot Alexa
Softshake 2017 - Développer un chatbot AlexaSoftshake 2017 - Développer un chatbot Alexa
Softshake 2017 - Développer un chatbot Alexa
 
Chatbots buzzword ou nouvel eldorado
Chatbots   buzzword ou nouvel eldoradoChatbots   buzzword ou nouvel eldorado
Chatbots buzzword ou nouvel eldorado
 
Management projet vs management produit
Management projet vs management produitManagement projet vs management produit
Management projet vs management produit
 
Softshake - Offline applications
Softshake - Offline applicationsSoftshake - Offline applications
Softshake - Offline applications
 
My Android is not an iPhone like any others (Mdevcon 2014)
My Android is not an iPhone like any others (Mdevcon 2014)My Android is not an iPhone like any others (Mdevcon 2014)
My Android is not an iPhone like any others (Mdevcon 2014)
 
DroidconUK 2013 : Beef up android apps with java tools
DroidconUK 2013 : Beef up android apps with java toolsDroidconUK 2013 : Beef up android apps with java tools
DroidconUK 2013 : Beef up android apps with java tools
 
Droidcon Paris 2013 - Musclez vos applications Android avec les outils du mon...
Droidcon Paris 2013 - Musclez vos applications Android avec les outils du mon...Droidcon Paris 2013 - Musclez vos applications Android avec les outils du mon...
Droidcon Paris 2013 - Musclez vos applications Android avec les outils du mon...
 
Devoxx France 2013 : Musclez vos apps android avec les outils du monde java
Devoxx France 2013 : Musclez vos apps android avec les outils du monde javaDevoxx France 2013 : Musclez vos apps android avec les outils du monde java
Devoxx France 2013 : Musclez vos apps android avec les outils du monde java
 
Jug Lausanne Android Janvier2013
Jug Lausanne Android Janvier2013Jug Lausanne Android Janvier2013
Jug Lausanne Android Janvier2013
 
Metroide
MetroideMetroide
Metroide
 

Recently uploaded

Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...apidays
 
A Beginners Guide to Building a RAG App Using Open Source Milvus
A Beginners Guide to Building a RAG App Using Open Source MilvusA Beginners Guide to Building a RAG App Using Open Source Milvus
A Beginners Guide to Building a RAG App Using Open Source MilvusZilliz
 
Ransomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfRansomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfOverkill Security
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024The Digital Insurer
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024The Digital Insurer
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot ModelNavi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot ModelDeepika Singh
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native ApplicationsWSO2
 
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...apidays
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businesspanagenda
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdflior mazor
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDropbox
 

Recently uploaded (20)

Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
A Beginners Guide to Building a RAG App Using Open Source Milvus
A Beginners Guide to Building a RAG App Using Open Source MilvusA Beginners Guide to Building a RAG App Using Open Source Milvus
A Beginners Guide to Building a RAG App Using Open Source Milvus
 
Ransomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfRansomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdf
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot ModelNavi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 

Do more with less code in a serverless world

  • 1. Less is more Do more with less code in a serverless world Jerome Van Der Linden Geneva Serverless Meetup - 26/05/2020
  • 2. About me • In a previous life, ”Mr Cut Cut” (M. Coupe coupe) • Developer & software craftsman • And now, Solutions Architect @ AWS 2 linkedin.com/in/jeromevdl/ Jerome Van Der Linden
  • 4. SOLID 4 S Single Responsibility Principle O Open / closed Principle L Liskov substitution Principle I Interface segregation Principle D Dependency Inversion Principle
  • 5. Single Responsibility Principle 5 “A class or module should have one, and only one, reason to be changed” - Robert C. Martin, aka Uncle Bob
  • 6. YAGNI (You Ain’t Gonna Need It) 6 Just because you can, doesn’t mean you should…
  • 8. 8 And many more… Clean Code DRY Don’t Repeat Yourself Law of Demeter Broken window theory Boy scout rule Not invented here
  • 9. How to apply those principles? In the serverless world
  • 10. Serverless World? 10 Serverless == FAASFunction As A Service
  • 11. Serverless World? 11 Serverless ⊃ FAASFunction As A Service
  • 12. AWS Serverless world 12 AWS Lambda AWS Fargate Amazon API Gateway Amazon SNS Amazon SQS COMPUTE DATA STORES INTEGRATION Amazon Aurora Serverless Amazon S3 Amazon DynamoDB Amazon EventBridge FAAS AWS Step Functions AWS AppSync
  • 13. Single Responsibility Principle ü Do’s ✘ Don’ts * - Input validation - Business logic /! - Transform data - Return result - Event/Input Filtering - Transport data - Orchestration & long transactions - Retry/Failure handling * Most of the time
  • 14. Event Filtering 15 SNS Topic Publisher if event_type == 'order_created’: lambda_client.invoke('OrderCreation', ...) elif event_type == 'order_placed’: lambda_client.invoke('OrderPlacement', ...) elif event_type == 'order_cancelled’: lambda_client.invoke('OrderCancelation', ...) OrderCreation OrderPlacement OrderCancellation { "event_type": "order_placed", "order": { "id": "232134", "amount": "2341,45", "stock_ref": "AMZN” } } the wrong way 𝝺 function code Input event OrderFiltering
  • 15. Event Filtering with SNS 16 OrderCreation OrderPlacement OrderCancellation Publisher OrderCreationEvent: Type: AWS::SNS::Subscription Properties: TopicArn: 'arn:aws:sns:eu-central-1:123456789:OrdersTopic’ Protocol: lambda Endpoint: 'arn:aws:lambda:eu-central-1:123456789:function:OrderCreation’ FilterPolicy: event_type: - order_created SNS Topic https://docs.aws.amazon.com/sns/latest/dg/sns-subscription-filter-policies.html Cloudformation template { "event_type": [ "order_created" ] } Filter policy
  • 16. Event Filtering with SNS 17 OrderCreation OrderPlacement OrderCancellation Publisher OrderPlacementEvent: Type: AWS::SNS::Subscription Properties: TopicArn: 'arn:aws:sns:eu-central-1:123456789:OrdersTopic’ Protocol: lambda Endpoint: 'arn:aws:lambda:eu-central-1:123456789:function:OrderPlacement’ FilterPolicy: event_type: - order_placed SNS Topic Cloudformation template
  • 17. Event Filtering with SNS 18 OrderCreation OrderPlacement OrderCancellation Publisher OrderCancellationEvent: Type: AWS::SNS::Subscription Properties: TopicArn: 'arn:aws:sns:eu-central-1:123456789:OrdersTopic’ Protocol: lambda Endpoint: 'arn:aws:lambda:eu-central-1:123456789:function:OrderCancellation’ FilterPolicy: event_type: - order_cancelled SNS Topic Cloudformation template
  • 18. Event Filtering with EventBridge 19 https://aws.amazon.com/blogs/compute/reducing-custom-code-by-using-advanced-rules-in-amazon-eventbridge/ { "Source": "custom.myATMapp", "EventBusName": "default", "DetailType": "transaction", "Time": "Wed Jan 29 2020 08:03:18 GMT-0500", "Detail":{ "action": "withdrawal", "location": "NY-NYC-001", "amount": 300, "result": "approved", "transactionId": "123456", "cardPresent": true, "partnerBank": "Example Bank", "remainingFunds": 722.34 } } { "source": [ "custom.myATMapp" ], "detail-type": [ "transaction" ], "detail": { "amount": [ { "numeric": [ ">", 300 ] } ] } } { "source": [ "custom.myATMapp" ], "detail-type": [ "transaction" ], "detail": { "location": [ { "prefix": "NY-NYC-" } ] } } { "source": [ "custom.myATMapp" ], "detail-type": [ "transaction" ], "detail": { "partnerBank": [ { "exists": true } ] } } { "source": [ "custom.myATMapp" ], "detail-type": [ "transaction" ], "detail": { "result": [ "approved" ], "partnerBank": [ { "exists": false } ], "location": [ { "anything-but": "NY-NYC-002" }] } }
  • 19. Orchestration 20 the wrong way invoke invokeif (… ) invoke // else if (success) Notify with SNS n * invoke if (failure) Enqueue error notify with SNS need approval App…
  • 20. Simple orchestration with Lambda destinations 21 invoke invokeif (… ) invoke // else if (success) Notify with SNS n * invoke if (failure) Enqueue error notify with SNS need approval App… Lambda Destinations
  • 21. Simple orchestration with Lambda destinations 22 Amazon SNS Amazon EventBridge Amazon Cloudwatch Logs Amazon S3 Amazon SES AWS Config Amazon CloudFormation AWS CodeCommit A S Y N C "DestinationConfig": { "onSuccess": { "Destination": "arn:aws:lambda:..." }, "onFailure": { "Destination": "arn:aws:sqs:..." } } Cloudformation template Amazon SNS Amazon EventBridge Amazon SQS AWS Lambda if success: return {...} else: raise Exception(‘Failure', {...}) 𝝺 function code Lambda function A S Y N C
  • 22. Advanced orchestration with Step Functions 23 invoke invokeif (… ) invoke // else if (success) Notify with SNS n * invoke if (failure) Enqueue error notify with SNS need approval App…
  • 23. Advanced orchestration with Step Functions 24 invoke invokeif (… ) invoke // else if (success) Notify with SNS n * invoke if (failure) Enqueue error notify with SNS need approval App… { "StartAt": "SimpleInvocation", "States": { "SimpleInvocation": { "Type": "Task", "Resource": "arn:aws:lambda:eu-central- 1:123456789012:function:HelloFunction", "Next": "Choose1or2" },
  • 24. Advanced orchestration with Step Functions 25 invoke invokeif (… ) invoke // else if (success) Notify with SNS n * invoke if (failure) Enqueue error notify with SNS need approval App… "Choose1or2": { "Type": "Choice", "Choices": [ { "Variable": "$.foo”, "NumericEquals": 1, "Next": "Lambda1" }, { "Variable": "$.foo", "NumericEquals": 2, "Next": "ParallelInvocation" } ], "Default": "Unmatched" },
  • 25. Advanced orchestration with Step Functions 26 invoke invokeif (… ) invoke // else if (success) Notify with SNS n * invoke if (failure) Enqueue error notify with SNS need approval App… "Lambda1": { "Type": "Task", "Resource": "arn:aws:lambda:eu- central-1:123456789012:function:Lambda1", "Next": "SuccessOrFailure" },
  • 26. Advanced orchestration with Step Functions 27 invoke invokeif (… ) invoke // else if (success) Notify with SNS n * invoke if (failure) Enqueue error notify with SNS need approval App… "SuccessOrFailure": { "Type": "Choice", "Choices": [ { "Variable": "$.status", "StringEquals": "SUCCESS", "Next": "SendNotification" }, { "Variable": "$.status", "StringEquals": "FAILURE", "Next": "QueueError" } ], "Default": "Unmatched" }
  • 27. Advanced orchestration with Step Functions 28 invoke invokeif (… ) invoke // else if (success) Notify with SNS n * invoke if (failure) Enqueue error notify with SNS need approval App… "SendNotification": { "Type": "Succeed" }, "QueueError": { "Type": "Fail" },
  • 28. Advanced orchestration with Step Functions 29 invoke invokeif (… ) invoke // else if (success) Notify with SNS n * invoke if (failure) Enqueue error notify with SNS need approval App… "ParallelInvocation": { "Type": "Parallel", "Branches": [ { "StartAt": "SendApprovalRequest", "States": { "SendApprovalRequest": { // ... } }, { "StartAt": "Loop", "States": { "Loop": { // ... } } }
  • 29. Advanced orchestration with Step Functions 30 invoke invokeif (… ) invoke // else if (success) Notify with SNS n * invoke if (failure) Enqueue error notify with SNS need approval App… "SendApprovalRequest": { "Type": "Task", "Resource": "arn:aws:states:::lambda:invoke.waitForTaskToken", "Parameters": { "FunctionName": "sendMailForApprovalFunction", "Payload": { "step.$": "$$.State.Name", "model.$": "$.data", "token.$": "$$.Task.Token" } }, "ResultPath": "$.output", "Next": "Approved", "Catch": [ { "ErrorEquals": [ "rejected" ], "ResultPath": "$.reason", "Next": "Rejected" } ] } SendTaskSuccess SendTaskFailure
  • 30. Advanced orchestration with Step Functions 31 invoke invokeif (… ) invoke // else if (success) Notify with SNS n * invoke if (failure) Enqueue error notify with SNS need approval App… "Loop": { "Type": "Map", "ItemsPath": "$.loopItems", "Iterator": { "StartAt": "LoopLambda", "States": { "LoopLambda": { "Type": "Task", "Resource": "arn:aws:lambda:us-east- 1:123456789012:function:LoopFunction", "End": true } } }, "End": true }
  • 31. Advanced orchestration with Step Functions 32 invoke invokeif (… ) invoke // else if (success) Notify with SNS n * invoke if (failure) Enqueue error notify with SNS need approval App…
  • 32. TL;DR Single Responsibility Principle 33 èKeep your 𝝺 code focused on the business This is not the responsibility of a 𝝺 to do orchestration
  • 33. You ain’t gonna need it 34 Welcome in the “functionless” world !
  • 35. Ex: insert data in DynamoDB 36 Resource: /comments HTTP Method: POST HTTP Request Body: { "pageId": "example-page-id", "userName": "ExampleUserName", "message": "Example comment to be added." } Table: Comments commentId: String userName: String message: String pageId: String PK: commentIdAPI Gateway DynamoDBLambda var AWS = require('aws-sdk'); var ddb = new AWS.DynamoDB({apiVersion: '2012-08-10'}); exports.handler = async function(event, context) { var params = { TableName: 'Comments’, Item: { 'commentId' : { S: 'randomid’ }, 'pageId' : { S: event.pageId }, 'userName' : { S: event.userName }, 'message' : { S: event.message } } }; ddb.putItem(params, function(err, data) { if (err) { console.log("Error", err); } else { console.log("Success", data); } }); }
  • 36. Ex: insert data in DynamoDB 37 Resource: /comments HTTP Method: POST HTTP Request Body: { "pageId": "example-page-id", "userName": "ExampleUserName", "message": "Example comment to be added." } Table: Comments commentId: String userName: String message: String pageId: String PK: commentIdAPI Gateway DynamoDB
  • 37. Ex: insert data in DynamoDB 38 Resource: /comments HTTP Method: POST HTTP Request Body: { "pageId": "example-page-id", "userName": "ExampleUserName", "message": "Example comment to be added." } Table: Comments commentId: String userName: String message: String pageId: String PK: commentIdAPI Gateway DynamoDB
  • 38. Ex: insert data in DynamoDB 39 Resource: /comments HTTP Method: POST HTTP Request Body: { "pageId": "example-page-id", "userName": "ExampleUserName", "message": "Example comment to be added." } Table: Comments commentId: String userName: String message: String pageId: String PK: commentIdAPI Gateway DynamoDB
  • 39. Ex: insert data in DynamoDB 40 Resource: /comments HTTP Method: POST HTTP Request Body: { "pageId": "example-page-id", "userName": "ExampleUserName", "message": "Example comment to be added." } Table: Comments commentId: String userName: String message: String pageId: String PK: commentIdAPI Gateway DynamoDB
  • 40. Ex: insert data in DynamoDB 41 Resource: /comments HTTP Method: POST HTTP Request Body: { "pageId": "example-page-id", "userName": "ExampleUserName", "message": "Example comment to be added." } Table: Comments commentId: String userName: String message: String pageId: String PK: commentIdAPI Gateway DynamoDB
  • 41. Use with caution 42 • Not a generic design pattern, not always applicable • Apply when the lambda is a passthrough (no business code, just mapping) • Mapping can sometimes be complex (Velocity Template Language)
  • 42. Step Function integrations 43 "QueueError": { "Type": "Task", "Resource": "arn:aws:states:::sqs:sendMessage", "Parameters": { "QueueUrl": "https://sqs.eu-central-1.amazonaws.com/123456789012/myQueue", "MessageBody.$": "$.input.message" }, "End": true }, "SendNotification": { "Type": "Task", "Resource": "arn:aws:states:::sns:publish", "Parameters": { "TopicARN": "arn:aws:sns:eu-central- 1:123456789012:myTopic", "Subject": "Lambda1 has successfully finish its job", "Message.$" : "$.input.message" }, "End": true }, SQS SNS
  • 43. Step Function integrations 44 AWS Batch Amazon DynamoDB Amazon ECS / Fargate Amazon EMR AWS Glue Amazon SageMaker Amazon SNS Amazon SQS AWS Step Functions AWS Lambda AWS CodeBuild
  • 44. TL;DR You Ain’t Gonna Need It 45 è 𝝺 is not always needed You can save costs and optimize performance when functions are just passthrough/mapping
  • 45. Keep it simple stupid 46 Lighten your functions
  • 46. Keep your functions simple & stupid nano functions API GW /res1 /res2 /res3 = 1 handler (1 function) = 1 file Not that stupid so they need sisters to do the job !
  • 47. Keep your functions simple & stupid nano functions API GW /res1 /res2 /res3 = 1 handler (1 function) = 1 file function-lith API GW /{proxy} /res1 /res2 /res3 That’s really not simple & stupid! = 1 handler (1 function) = 1 file
  • 48. Keep your functions simple & stupid nano functions API GW /res1 /res2 /res3 function-lith API GW /{proxy} /res1 /res2 /res3 = 1 handler (1 function) = 1 file fat functions API GW /res1 /res2 /res3 = 3 handlers (3 functions) = 1 file = 1 handler (1 function) = 1 file
  • 49. Keep your functions simple & stupid 50 nano functions API GW /res1 /res2 /res3 function-lith API GW /{proxy} /res1 /res2 /res3 fat functions = 1 handler (1 function) = 1 file API GW = 3 handler (3 functions) = 1 file micro functions API GW /res1 /res2 /res3 /res1 /res2 /res3 = 1 handler (1 function) = 1 file = 1 handler (1 function) = 1 file
  • 50. Keep your functions simple & stupid https://github.com/cdk-patterns/serverless/tree/master/the-lambda-trilogy Potential duplicated code ++ Cognitive burden ++ Coupled functions Coupled deployments nano functions API GW /res1 /res2 /res3 function-lith API GW /{proxy} /res1 /res2 /res3 fat functions = 1 handler (1 function) = 1 file API GW = 3 handler (3 functions) = 1 file micro functions /res1 /res2 /res3 = 1 handler (1 function) = 1 file API GW /res1 /res2 /res3 = 1 handler (1 function) = 1 file Stupidity Complexity FAAS? Longer cold starts ++ Risk of blast radius Framework dependent Longer cold starts Risk of blast radius Potential duplicated code Cognitive burden
  • 51. TL;DR Keep it simple stupid 52 Lighter functions = Easier to test and maintain Faster to start: less cold start More scalable: higher throughput More secure: less permission needed
  • 52. Conclusion No function is easier to manage than ‘no function’ – me è If you can do better without a function, just do it è Else, apply software craftsmanship principles (clean code, tests, code reviews…) “No server is easier to manage than ‘no server’” – Werner Vogels
  • 55. AWSTemplateFormatVersion: 2010-09-09 Resources: API: Type: AWS::ApiGateway::RestApi Properties: Name: !Sub ${AWS::StackName}-api- ${AWS::AccountId} APIDeployment: Type: AWS::ApiGateway::Deployment Properties: RestApiId: !Ref API StageName: prod DependsOn: - ListBucketAPI APIBucketResource: Type: AWS::ApiGateway::Resource Properties: ParentId: !GetAtt API.RootResourceId PathPart: "{bucket}" RestApiId: !Ref API ListBucketAPI: Type: AWS::ApiGateway::Method Properties: HttpMethod: GET ResourceId: !Ref APIBucketResource RestApiId: !Ref API AuthorizationType: NONE Integration: Credentials: 'arn:aws:iam::1234567890:role/role-demo-api-gw-s3-integration’ IntegrationHttpMethod: GET IntegrationResponses: - StatusCode: "200" PassthroughBehavior: WHEN_NO_MATCH RequestParameters: integration.request.header.Content-Type: method.request.header.Content-Type integration.request.header.x-amz-acl: "'authenticated-read’” integration.request.path.bucket: method.request.path.bucket Type: AWS Uri: !Sub arn:aws:apigateway:${AWS::Region}:s3:path/{bucket} MethodResponses: - StatusCode: "200" RequestParameters: method.request.path.bucket: true method.request.header.Content-Type: false API Gateway & S3 sample https://docs.aws.amazon.com/apigateway/latest/developerguide/integrating-api-with-aws-services-s3.html
  • 56. 57 Advanced orchestration with Step Functions{ "StartAt": "SimpleInvocation", "States": { "SimpleInvocation": { "Type": "Task", "Resource": "arn:aws:lambda:eu-central-1:123456789012:function:HelloFunction", "Next": "Choose1or2" }, "Choose1or2": { "Type": "Choice", "Choices": [ { "Variable": "$.foo", "NumericEquals": 1, "Next": "Lambda1" }, { "Variable": "$.foo", "NumericEquals": 2, "Next": "ParallelInvocation" } ], "Default": "Unmatched" }, "Lambda1": { "Type": "Task", "Resource": "arn:aws:lambda:eu-central-1:123456789012:function:Lambda1", "Next": "SuccessOrFailure" }, "SuccessOrFailure": { "Type": "Choice", "Choices": [ { "Variable": "$.status", "StringEquals": "SUCCESS", "Next": "SendNotification" }, { "Variable": "$.status", "StringEquals": "FAILURE", "Next": "QueueError" } ], "Default": "Unmatched" }, "SendNotification": { "Type": "Succeed" }, "QueueError": { "Type": "Fail" }, "ParallelInvocation": { "Type": "Parallel", "Branches": [ { "StartAt": "SendApprovalRequest", "States": { "SendApprovalRequest": { "Type": "Task", "Resource": "arn:aws:states:::lambda:invoke.waitForTaskToken", "Parameters": { "FunctionName": "sendMailForApprovalFunction", "Payload": { "step.$": "$$.State.Name", "model.$": "$.data", "token.$": "$$.Task.Token" } }, "ResultPath": "$.output", "Next": "Approved", "Catch": [ { "ErrorEquals": [ "rejected" ], "ResultPath": "$.reason", "Next": "Rejected" } ] }, "Approved": { "Type": "Task", "Resource": "arn:aws:lambda:eu-central-1:123456789012:function:Lambda1", "End": true }, "Rejected": { "Type": "Fail" } } }, { "StartAt": "Loop", "States": { "Loop": { "Type": "Map", "ItemsPath": "$.loopItems", "Iterator": { "StartAt": "LoopLambda", "States": { "LoopLambda": { "Type": "Task", "Resource": "arn:aws:lambda:us-east-1:123456789012:function:LoopFunction", "End": true } } }, "End": true } } } ], "End": true }, "Unmatched": { "Type": "Fail", "Error": "DefaultStateError", "Cause": "No Matches!" } } }