SlideShare a Scribd company logo
from
Big Band Web App
to
Serverless
Bebop
@AnjanaVakil JazzCon.Tech 2018
Hello!
I’m @AnjanaVakil
Recurse Center Non-Graduate
Mozilla TechSpeaker & Outreachy Alumna
Engineering Learning & Development Lead, Mapbox
location data platform for developers
maps, search, navigation
web, iOS, Android, Unity...
@AnjanaVakil JazzCon.Tech 2018
@AnjanaVakil JazzCon.Tech 2018
we use to
◍ get user stats
◍ monitor/test unpacker
uploads
◍ ask yoda who’s on call
◍ see who’s out tmrw
◍ pick a random teammate
Place your screenshot here
@AnjanaVakil JazzCon.Tech 2018
user-
limits
out
unpackeryoda
stats
Express
slack i/o
auth
our slack-commands app
node
@AnjanaVakil JazzCon.Tech 2018
codebase
slack-commands/
├─ readme.md
├─ cloudformation/ #app & cmd config
│ └─ slack-commands.template.js
├─ index.js #express app
├─ commands/
│ ├─ out.js
│ ├─ stats.js
│ └─ ...
└─ test/
├─ index.test.js
├─ out.test.js
├─ stats.test.js
└─ ...
@AnjanaVakil JazzCon.Tech 2018
All commands in a single app: Downsides
Security
◍ Permissions?
Secrets?
◍ Least privilege
Maintenance
◍ Many different
teams involved
◍ Ownership?
Support?
◍ Code gumbo
Cost
◍ Always running
◍ No per-command
breakdown
@AnjanaVakil JazzCon.Tech 2018
enough
about computers
let’s talk about jazz
@AnjanaVakil JazzCon.Tech 2018
“
While swing music tended to feature
orchestrated big band arrangements,
bebop music highlighted improvisation.
@AnjanaVakil JazzCon.Tech 2018
wikipedia
Big Band
Glenn Miller Orchestra, c. 1940
Big Band
out unpacker
status
yoda
Express
slack i/o
auth
user-
limits
@AnjanaVakil JazzCon.Tech 2018
“I kept thinking there's bound to be something
else. I could hear it sometimes. I couldn't play it....
I found that by using the higher intervals of a
chord as a melody line and backing them with
appropriately related changes, I could play the
thing I'd been hearing. It came alive.
- Charlie Parker
@AnjanaVakil JazzCon.Tech 2018
wikipedia
Bebop
Tommy Potter, Charlie Parker, Max Roach, Miles Davis, & Duke Jordan, NYC c. 1945
“As bebop was not intended for dancing, it
enabled the musicians to play at faster tempos.
Bebop musicians explored advanced harmonies,
complex syncopation, altered chords, extended
chords, chord substitutions, asymmetrical
phrasing, and intricate melodies.
@AnjanaVakil JazzCon.Tech 2018
wikipedia
Bebop
out
unpacker
status
yoda user-limits
@AnjanaVakil JazzCon.Tech 2018
“there’s bound to be something else”
◍ Assign a single owner/gatekeeper?
◍ Multiple single-command apps?
◍ Separate commands from router app
@AnjanaVakil JazzCon.Tech 2018
“serverless” functions to the rescue
AWS Lambda
@AnjanaVakil JazzCon.Tech 2018
what do you mean “serverless”
Actual Server
You own a computer
You put code on it
You run it constantly
(and you pay constantly)
You keep it healthy
Cloud Server
AWS owns a computer (or 2)
You put code on it
AWS runs it constantly
(and you pay constantly)
You tell AWS how to keep
it healthy
“No” Server
AWS owns a computer
You put code on it
AWS runs it when you ask
(and you pay only then)
AWS keeps it healthy
@AnjanaVakil JazzCon.Tech 2018
◍ Only concern: Input -> Output
◍ No state maintained between calls
◍ Can be side-effecting, though
(e.g. API call, database write)
◍ Limited resources & exec time (5m)
what do you mean “function”
@AnjanaVakil JazzCon.Tech 2018
Lose the server if it’s...
◍ small
◍ short-lived
◍ self-contained
◍ needed occasionally
to lambda or not to lambda
Keep the server if it’s...
◍ heavy
◍ long-running
◍ interdependent
◍ needed constantly
@AnjanaVakil JazzCon.Tech 2018
HTTP API
endpoint
AWS
load
balancerEC2s on ECS
JS
JSJS
old architecture
@AnjanaVakil JazzCon.Tech 2018
HTTP API
endpoint
router
new architecture
stats
out
unpacker
yoda
@AnjanaVakil JazzCon.Tech 2018
old
codebase
slack-commands/
├─ readme.md
├─ cloudformation/ #app & cmd config
│ └─ slack-commands.template.js
├─ index.js #express app code
├─ commands/ #cmd code
│ ├─ out.js
│ ├─ stats.js
│ └─ ...
└─ test/ #app & cmd tests
├─ index.test.js
├─ out.test.js
├─ stats.test.js
└─ ...
@AnjanaVakil JazzCon.Tech 2018
new
codebase
slack-commands/
├─ readme.md
├─ cloudformation/ #app config
│ └─ slack-commands.template.js
├─ index.js #express app code
├─ commander.js #invoke lambdas
└─ test/
├─ commander.test.js
└─ index.test.js
slack-command-{cmd}/
├ readme.md
├ cloudformation/ #cmd config
│ └ slack-command-{cmd}.template.js
├ index.js #cmd code
└ test/
└ index.test.js@AnjanaVakil JazzCon.Tech 2018
what does a
function
look like?
@AnjanaVakil JazzCon.Tech 2018
Place your screenshot here
user stats commmand
@AnjanaVakil JazzCon.Tech 2018
module.exports.command = (event, context, callback) => {
const { ApiCoreUrl, MapboxToken } = process.env;
const user = event.args[0];
const from = new Date(event.args[1] || (+new Date - 864e5*30)); // 30d
const to = new Date(event.args[2] || (+new Date));
if (isNaN(from)||isNaN(to)) return callback(new Error('invalid date'));
const requrl = getStatsUrl(user, from, to, ApiCoreUrl, MapboxToken);
request(requrl, (err, res, body) => {
if (err||res.statusCode !== 200) return callback(err||res.statusCode);
try { const data = JSON.parse(body); }
catch(err) { return callback(err); }
return callback(null, formatStatsMessage(user, data));
});
}
@AnjanaVakil JazzCon.Tech 2018
module.exports.command = (event, context, callback) => {
const { ApiCoreUrl, MapboxToken } = process.env;
const user = event.args[0];
const from = new Date(event.args[1] || (+new Date - 864e5*30)); // 30d
const to = new Date(event.args[2] || (+new Date));
if (isNaN(from)||isNaN(to)) return callback(new Error('invalid date'));
const requrl = getStatsUrl(user, from, to, ApiCoreUrl, MapboxToken);
request(requrl, (err, res, body) => {
if (err||res.statusCode !== 200) return callback(err||res.statusCode);
try { const data = JSON.parse(body); }
catch(err) { return callback(err); }
return callback(null, formatStatsMessage(user, data));
});
}
handler function
(we tell Lambda its name)
@AnjanaVakil JazzCon.Tech 2018
module.exports.command = (event, context, callback) => {
const { ApiCoreUrl, MapboxToken } = process.env;
const user = event.args[0];
const from = new Date(event.args[1] || (+new Date - 864e5*30)); // 30d
const to = new Date(event.args[2] || (+new Date));
if (isNaN(from)||isNaN(to)) return callback(new Error('invalid date'));
const requrl = getStatsUrl(user, from, to, ApiCoreUrl, MapboxToken);
request(requrl, (err, res, body) => {
if (err||res.statusCode !== 200) return callback(err||res.statusCode);
try { const data = JSON.parse(body); }
catch(err) { return callback(err); }
return callback(null, formatStatsMessage(user, data));
});
}
execution environment
we can configure
@AnjanaVakil JazzCon.Tech 2018
module.exports.command = (event, context, callback) => {
const { ApiCoreUrl, MapboxToken } = process.env;
const user = event.args[0];
const from = new Date(event.args[1] || (+new Date - 864e5*30)); // 30d
const to = new Date(event.args[2] || (+new Date));
if (isNaN(from)||isNaN(to)) return callback(new Error('invalid date'));
const requrl = getStatsUrl(user, from, to, ApiCoreUrl, MapboxToken);
request(requrl, (err, res, body) => {
if (err||res.statusCode !== 200) return callback(err||res.statusCode);
try { const data = JSON.parse(body); }
catch(err) { return callback(err); }
return callback(null, formatStatsMessage(user, data));
});
}
input { args: [ “vakila”, “1/1”, “3/22”] }
@AnjanaVakil JazzCon.Tech 2018
module.exports.command = (event, context, callback) => {
const { ApiCoreUrl, MapboxToken } = process.env;
const user = event.args[0];
const from = new Date(event.args[1] || (+new Date - 864e5*30)); // 30d
const to = new Date(event.args[2] || (+new Date));
if (isNaN(from)||isNaN(to)) return callback(new Error('invalid date'));
const requrl = getStatsUrl(user, from, to, ApiCoreUrl, MapboxToken);
request(requrl, (err, res, body) => {
if (err||res.statusCode !== 200) return callback(err||res.statusCode);
try { const data = JSON.parse(body); }
catch(err) { return callback(err); }
return callback(null, formatStatsMessage(user, data));
});
}
aws runtime info
(e.g. time remaining - ignored here)
@AnjanaVakil JazzCon.Tech 2018
module.exports.command = (event, context, callback) => {
const { ApiCoreUrl, MapboxToken } = process.env;
const user = event.args[0];
const from = new Date(event.args[1] || (+new Date - 864e5*30)); // 30d
const to = new Date(event.args[2] || (+new Date));
if (isNaN(from)||isNaN(to)) return callback(new Error('invalid date'));
const requrl = getStatsUrl(user, from, to, ApiCoreUrl, MapboxToken);
request(requrl, (err, res, body) => {
if (err||res.statusCode !== 200) return callback(err||res.statusCode);
try { const data = JSON.parse(body); }
catch(err) { return callback(err); }
return callback(null, formatStatsMessage(user, data));
});
}
“ok, I’m done” function
(AWS passes this when executing)
error data
@AnjanaVakil JazzCon.Tech 2018
we wrote a function!
yay
@AnjanaVakil JazzCon.Tech 2018
do we get it up there?
how
@AnjanaVakil JazzCon.Tech 2018
Cloud::Formation templates
◍ JSON template - “just code”
◍ define your AWS stack components
◍ upload -> AWS builds your stack
@AnjanaVakil JazzCon.Tech 2018
Cloud::Formation templates
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "slack-command-stats",
"Parameters": { "ApiCoreUrl": {...}, "MapboxToken": {...}
"Resources": {
"Command": {
"Type": "AWS::Lambda::Function",
"Properties": {...}
},
"CommandRole": {
"Type": "AWS::IAM::Role",
"Properties": {...}
}
},
"Outputs": { ... }
}
@AnjanaVakil JazzCon.Tech 2018
Cloud::Formation templates
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "slack-command-stats",
"Parameters": { "ApiCoreUrl": {...}, "MapboxToken": {...}
"Resources": {
"Command": {
"Type": "AWS::Lambda::Function",
"Properties": {...}
},
"CommandRole": {
"Type": "AWS::IAM::Role",
"Properties": {...}
}
},
"Outputs": { ... }
}
stack
input
params
@AnjanaVakil JazzCon.Tech 2018
Cloud::Formation templates
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "slack-command-stats",
"Parameters": { "ApiCoreUrl": {...}, "MapboxToken": {...}
"Resources": {
"Command": {
"Type": "AWS::Lambda::Function",
"Properties": {...}
},
"CommandRole": {
"Type": "AWS::IAM::Role",
"Properties": {...}
}
},
"Outputs": { ... }
}
aws
permissions
for function
@AnjanaVakil JazzCon.Tech 2018
Cloud::Formation templates
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "slack-command-stats",
"Parameters": { "ApiCoreUrl": {...}, "MapboxToken": {...}
"Resources": {
"Command": {
"Type": "AWS::Lambda::Function",
"Properties": {...}
},
"CommandRole": {
"Type": "AWS::IAM::Role",
"Properties": {...}
}
},
"Outputs": { ... }
}
actual
lambda
function
the good stuff
@AnjanaVakil JazzCon.Tech 2018
Cloud::Formation templates
"Command": {
"Type": "AWS::Lambda::Function",
"Properties": {
"FunctionName": "slack-command-stats-production",
"Code": { "S3Bucket": {...}, "S3Key": {...} },
"Handler": "index.command",
"Environment": { "Variables": {
"ApiCoreUrl": { "Ref": "ApiCoreUrl" },
"MapboxToken": { "Ref": "MapboxToken" } } },
"Role": { "Fn::GetAtt": ["CommandRole","Arn"] },
"Runtime": "nodejs4.3", "MemorySize": 128, "Timeout": 60,
"Tags": [ { "Key": "Team", "Value": "EngOps"} ]
}
}
@AnjanaVakil JazzCon.Tech 2018
Cloud::Formation templates
"Command": {
"Type": "AWS::Lambda::Function",
"Properties": {
"FunctionName": "slack-command-stats-production",
"Code": { "S3Bucket": {...}, "S3Key": {...} },
"Handler": "index.command",
"Environment": { "Variables": {
"ApiCoreUrl": { "Ref": "ApiCoreUrl" },
"MapboxToken": { "Ref": "MapboxToken" } } },
"Role": { "Fn::GetAtt": ["CommandRole","Arn"] },
"Runtime": "nodejs4.3", "MemorySize": 128, "Timeout": 60,
"Tags": [ { "Key": "Team", "Value": "EngOps"} ]
}
}
@AnjanaVakil JazzCon.Tech 2018
function
name
helps find it later
Cloud::Formation templates
"Command": {
"Type": "AWS::Lambda::Function",
"Properties": {
"FunctionName": "slack-command-stats-production",
"Code": { "S3Bucket": {...}, "S3Key": {...} },
"Handler": "index.command",
"Environment": { "Variables": {
"ApiCoreUrl": { "Ref": "ApiCoreUrl" },
"MapboxToken": { "Ref": "MapboxToken" } } },
"Role": { "Fn::GetAtt": ["CommandRole","Arn"] },
"Runtime": "nodejs4.3", "MemorySize": 128, "Timeout": 60,
"Tags": [ { "Key": "Team", "Value": "EngOps"} ]
}
}
@AnjanaVakil JazzCon.Tech 2018
code to run
the good stuff
Cloud::Formation templates
"Command": {
"Type": "AWS::Lambda::Function",
"Properties": {
"FunctionName": "slack-command-stats-production",
"Code": { "S3Bucket": {...}, "S3Key": {...} },
"Handler": "index.command",
"Environment": { "Variables": {
"ApiCoreUrl": { "Ref": "ApiCoreUrl" },
"MapboxToken": { "Ref": "MapboxToken" } } },
"Role": { "Fn::GetAtt": ["CommandRole","Arn"] },
"Runtime": "nodejs4.3", "MemorySize": 128, "Timeout": 60,
"Tags": [ { "Key": "Team", "Value": "EngOps"} ]
}
}
@AnjanaVakil JazzCon.Tech 2018
execution
environment
can pass in params
Cloud::Formation templates
"Command": {
"Type": "AWS::Lambda::Function",
"Properties": {
"FunctionName": "slack-command-stats-production",
"Code": { "S3Bucket": {...}, "S3Key": {...} },
"Handler": "index.command",
"Environment": { "Variables": {
"ApiCoreUrl": { "Ref": "ApiCoreUrl" },
"MapboxToken": { "Ref": "MapboxToken" } } },
"Role": { "Fn::GetAtt": ["CommandRole","Arn"] },
"Runtime": "nodejs4.3", "MemorySize": 128, "Timeout": 60,
"Tags": [ { "Key": "Team", "Value": "EngOps"} ]
}
}
@AnjanaVakil JazzCon.Tech 2018
permissions
from earlier
Cloud::Formation templates
"Command": {
"Type": "AWS::Lambda::Function",
"Properties": {
"FunctionName": "slack-command-stats-production",
"Code": { "S3Bucket": {...}, "S3Key": {...} },
"Handler": "index.command",
"Environment": { "Variables": {
"ApiCoreUrl": { "Ref": "ApiCoreUrl" },
"MapboxToken": { "Ref": "MapboxToken" } } },
"Role": { "Fn::GetAtt": ["CommandRole","Arn"] },
"Runtime": "nodejs4.3", "MemorySize": 128, "Timeout": 60,
"Tags": [ { "Key": "Team", "Value": "EngOps"} ]
}
}
@AnjanaVakil JazzCon.Tech 2018
what to run it on
totally not a server
Cloud::Formation templates
"Command": {
"Type": "AWS::Lambda::Function",
"Properties": {
"FunctionName": "slack-command-stats-production",
"Code": { "S3Bucket": {...}, "S3Key": {...} },
"Handler": "index.command",
"Environment": { "Variables": {
"ApiCoreUrl": { "Ref": "ApiCoreUrl" },
"MapboxToken": { "Ref": "MapboxToken" } } },
"Role": { "Fn::GetAtt": ["CommandRole","Arn"] },
"Runtime": "nodejs4.3", "MemorySize": 128, "Timeout": 60,
"Tags": [ { "Key": "Team", "Value": "EngOps"} ]
}
}
@AnjanaVakil JazzCon.Tech 2018
arbitrary tags
e.g. who owns this?
Mapbox open-source AWS
helpers
github.com/mapbox/
Command-line tools
lambda-cfn create & deploy Node Lambda functions
cfn-config configure/start/update CFN stacks
JS libraries
cloudfriend easily assemble CFN templates in JS
decrypt-kms-env use secret environment vars
@AnjanaVakil JazzCon.Tech 2018
we deployed a function!
yay
@AnjanaVakil JazzCon.Tech 2018
do we call it?
how
@AnjanaVakil JazzCon.Tech 2018
testing in the AWS console (manually)
@AnjanaVakil JazzCon.Tech 2018
in Node with AWS SDK
const AWS = require('aws-sdk');
const runCommand = (req, res, next) => {
const [commandName, ...args] = = req.slackText;
const params = {
FunctionName: `slack-command-${commandName}-production`, // our convention
Payload: JSON.stringify({ args: args }), // the `event` Lambda receives
};
const lambda = new AWS.Lambda({ region: 'us-east-1' });
lambda.invoke(params).promise()
.catch((err) => err.message) // pass on error message as response data
.then((data) => res.json(formatForSlack(data)));
};
@AnjanaVakil JazzCon.Tech 2018
why
did we do all that?
@AnjanaVakil JazzCon.Tech 2018
Before (single app)
◍ Many secrets in one
stack
◍ Updating your code
updates whole stack
◍ No fine-grained cost
analysis
Refactoring to Lambda: Benefits
After (multiple Lambdas)
◍ Each stack only knows
its own secrets
◍ Updating your code
leaves others untouched
◍ Each stack/fn can be
tagged & cost-monitored
@AnjanaVakil JazzCon.Tech 2018
HTTP API
endpoint
router
next steps
stats
out
unpacker
yoda
@AnjanaVakil JazzCon.Tech 2018
HTTP API
endpoint
next steps
stats
out
unpacker
yoda
@AnjanaVakil JazzCon.Tech 2018
router
Merci!
@AnjanaVakil
anjana@mapbox.com
✌ Team Mapbox
Young Hahn, Emily McAfee,
Kelly Young, Jake Pruitt, Andrew Evans
JazzCon.Tech Organizers
Images from Wikimedia
Template by SlidesCarnival.com

More Related Content

What's hot

Business Dashboards using Bonobo ETL, Grafana and Apache Airflow
Business Dashboards using Bonobo ETL, Grafana and Apache AirflowBusiness Dashboards using Bonobo ETL, Grafana and Apache Airflow
Business Dashboards using Bonobo ETL, Grafana and Apache Airflow
Romain Dorgueil
 
Scaling up data science applications
Scaling up data science applicationsScaling up data science applications
Scaling up data science applications
Kexin Xie
 
Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6
Ignacio Martín
 
Reactive programming on Android
Reactive programming on AndroidReactive programming on Android
Reactive programming on Android
Tomáš Kypta
 
Understanding reactive programming with microsoft reactive extensions
Understanding reactive programming  with microsoft reactive extensionsUnderstanding reactive programming  with microsoft reactive extensions
Understanding reactive programming with microsoft reactive extensions
Oleksandr Zhevzhyk
 
Reactive programming every day
Reactive programming every dayReactive programming every day
Reactive programming every day
Vadym Khondar
 
Scala.js: Next generation front end development in Scala
Scala.js:  Next generation front end development in ScalaScala.js:  Next generation front end development in Scala
Scala.js: Next generation front end development in Scala
Otto Chrons
 
The redux saga begins
The redux saga beginsThe redux saga begins
The redux saga begins
Daniel Franz
 
Redux Sagas - React Alicante
Redux Sagas - React AlicanteRedux Sagas - React Alicante
Redux Sagas - React Alicante
Ignacio Martín
 
A dive into akka streams: from the basics to a real-world scenario
A dive into akka streams: from the basics to a real-world scenarioA dive into akka streams: from the basics to a real-world scenario
A dive into akka streams: from the basics to a real-world scenario
Gioia Ballin
 
Firebase ng2 zurich
Firebase ng2 zurichFirebase ng2 zurich
Firebase ng2 zurich
Christoffer Noring
 
Spark Your Legacy (Spark Summit 2016)
Spark Your Legacy (Spark Summit 2016)Spark Your Legacy (Spark Summit 2016)
Spark Your Legacy (Spark Summit 2016)
Tzach Zohar
 
Using Redux-Saga for Handling Side Effects
Using Redux-Saga for Handling Side EffectsUsing Redux-Saga for Handling Side Effects
Using Redux-Saga for Handling Side Effects
GlobalLogic Ukraine
 
The evolution of redux action creators
The evolution of redux action creatorsThe evolution of redux action creators
The evolution of redux action creators
George Bukhanov
 
Reactive Programming - ReactFoo 2020 - Aziz Khambati
Reactive Programming - ReactFoo 2020 - Aziz KhambatiReactive Programming - ReactFoo 2020 - Aziz Khambati
Reactive Programming - ReactFoo 2020 - Aziz Khambati
Aziz Khambati
 
Swift Ready for Production?
Swift Ready for Production?Swift Ready for Production?
Swift Ready for Production?
Crispy Mountain
 
Using akka streams to access s3 objects
Using akka streams to access s3 objectsUsing akka streams to access s3 objects
Using akka streams to access s3 objects
Mikhail Girkin
 
WattGo: Analyses temps-réél de series temporelles avec Spark et Solr (Français)
WattGo: Analyses temps-réél de series temporelles avec Spark et Solr (Français)WattGo: Analyses temps-réél de series temporelles avec Spark et Solr (Français)
WattGo: Analyses temps-réél de series temporelles avec Spark et Solr (Français)
DataStax Academy
 
Barbara Nelson [InfluxData] | How Can I Put That Dashboard in My App? | Influ...
Barbara Nelson [InfluxData] | How Can I Put That Dashboard in My App? | Influ...Barbara Nelson [InfluxData] | How Can I Put That Dashboard in My App? | Influ...
Barbara Nelson [InfluxData] | How Can I Put That Dashboard in My App? | Influ...
InfluxData
 
Async Redux Actions With RxJS - React Rally 2016
Async Redux Actions With RxJS - React Rally 2016Async Redux Actions With RxJS - React Rally 2016
Async Redux Actions With RxJS - React Rally 2016
Ben Lesh
 

What's hot (20)

Business Dashboards using Bonobo ETL, Grafana and Apache Airflow
Business Dashboards using Bonobo ETL, Grafana and Apache AirflowBusiness Dashboards using Bonobo ETL, Grafana and Apache Airflow
Business Dashboards using Bonobo ETL, Grafana and Apache Airflow
 
Scaling up data science applications
Scaling up data science applicationsScaling up data science applications
Scaling up data science applications
 
Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6
 
Reactive programming on Android
Reactive programming on AndroidReactive programming on Android
Reactive programming on Android
 
Understanding reactive programming with microsoft reactive extensions
Understanding reactive programming  with microsoft reactive extensionsUnderstanding reactive programming  with microsoft reactive extensions
Understanding reactive programming with microsoft reactive extensions
 
Reactive programming every day
Reactive programming every dayReactive programming every day
Reactive programming every day
 
Scala.js: Next generation front end development in Scala
Scala.js:  Next generation front end development in ScalaScala.js:  Next generation front end development in Scala
Scala.js: Next generation front end development in Scala
 
The redux saga begins
The redux saga beginsThe redux saga begins
The redux saga begins
 
Redux Sagas - React Alicante
Redux Sagas - React AlicanteRedux Sagas - React Alicante
Redux Sagas - React Alicante
 
A dive into akka streams: from the basics to a real-world scenario
A dive into akka streams: from the basics to a real-world scenarioA dive into akka streams: from the basics to a real-world scenario
A dive into akka streams: from the basics to a real-world scenario
 
Firebase ng2 zurich
Firebase ng2 zurichFirebase ng2 zurich
Firebase ng2 zurich
 
Spark Your Legacy (Spark Summit 2016)
Spark Your Legacy (Spark Summit 2016)Spark Your Legacy (Spark Summit 2016)
Spark Your Legacy (Spark Summit 2016)
 
Using Redux-Saga for Handling Side Effects
Using Redux-Saga for Handling Side EffectsUsing Redux-Saga for Handling Side Effects
Using Redux-Saga for Handling Side Effects
 
The evolution of redux action creators
The evolution of redux action creatorsThe evolution of redux action creators
The evolution of redux action creators
 
Reactive Programming - ReactFoo 2020 - Aziz Khambati
Reactive Programming - ReactFoo 2020 - Aziz KhambatiReactive Programming - ReactFoo 2020 - Aziz Khambati
Reactive Programming - ReactFoo 2020 - Aziz Khambati
 
Swift Ready for Production?
Swift Ready for Production?Swift Ready for Production?
Swift Ready for Production?
 
Using akka streams to access s3 objects
Using akka streams to access s3 objectsUsing akka streams to access s3 objects
Using akka streams to access s3 objects
 
WattGo: Analyses temps-réél de series temporelles avec Spark et Solr (Français)
WattGo: Analyses temps-réél de series temporelles avec Spark et Solr (Français)WattGo: Analyses temps-réél de series temporelles avec Spark et Solr (Français)
WattGo: Analyses temps-réél de series temporelles avec Spark et Solr (Français)
 
Barbara Nelson [InfluxData] | How Can I Put That Dashboard in My App? | Influ...
Barbara Nelson [InfluxData] | How Can I Put That Dashboard in My App? | Influ...Barbara Nelson [InfluxData] | How Can I Put That Dashboard in My App? | Influ...
Barbara Nelson [InfluxData] | How Can I Put That Dashboard in My App? | Influ...
 
Async Redux Actions With RxJS - React Rally 2016
Async Redux Actions With RxJS - React Rally 2016Async Redux Actions With RxJS - React Rally 2016
Async Redux Actions With RxJS - React Rally 2016
 

Similar to JS Fest 2019. Anjana Vakil. Serverless Bebop

Lambdas puzzler - Peter Lawrey
Lambdas puzzler - Peter LawreyLambdas puzzler - Peter Lawrey
Lambdas puzzler - Peter Lawrey
JAXLondon_Conference
 
RxJava applied [JavaDay Kyiv 2016]
RxJava applied [JavaDay Kyiv 2016]RxJava applied [JavaDay Kyiv 2016]
RxJava applied [JavaDay Kyiv 2016]
Igor Lozynskyi
 
Compose Async with RxJS
Compose Async with RxJSCompose Async with RxJS
Compose Async with RxJS
Kyung Yeol Kim
 
MongoDB World 2019: Life In Stitch-es
MongoDB World 2019: Life In Stitch-esMongoDB World 2019: Life In Stitch-es
MongoDB World 2019: Life In Stitch-es
MongoDB
 
Expert JavaScript tricks of the masters
Expert JavaScript  tricks of the mastersExpert JavaScript  tricks of the masters
Expert JavaScript tricks of the masters
Ara Pehlivanian
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node js
Francois Zaninotto
 
Developing web-apps like it's 2013
Developing web-apps like it's 2013Developing web-apps like it's 2013
Developing web-apps like it's 2013
Laurent_VB
 
Wprowadzenie do technologii Big Data / Intro to Big Data Ecosystem
Wprowadzenie do technologii Big Data / Intro to Big Data EcosystemWprowadzenie do technologii Big Data / Intro to Big Data Ecosystem
Wprowadzenie do technologii Big Data / Intro to Big Data Ecosystem
Sages
 
Wprowadzenie do technologi Big Data i Apache Hadoop
Wprowadzenie do technologi Big Data i Apache HadoopWprowadzenie do technologi Big Data i Apache Hadoop
Wprowadzenie do technologi Big Data i Apache Hadoop
Sages
 
用 Go 語言打造多台機器 Scale 架構
用 Go 語言打造多台機器 Scale 架構用 Go 語言打造多台機器 Scale 架構
用 Go 語言打造多台機器 Scale 架構
Bo-Yi Wu
 
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
InfluxData
 
Coding Ajax
Coding AjaxCoding Ajax
Coding Ajax
Ted Husted
 
The Return of JavaScript: 3 Open-Source Projects that are driving JavaScript'...
The Return of JavaScript: 3 Open-Source Projects that are driving JavaScript'...The Return of JavaScript: 3 Open-Source Projects that are driving JavaScript'...
The Return of JavaScript: 3 Open-Source Projects that are driving JavaScript'...
Ben Teese
 
Analytics with Spark
Analytics with SparkAnalytics with Spark
Analytics with Spark
Probst Ludwine
 
GraphQL Bangkok Meetup 2.0
GraphQL Bangkok Meetup 2.0GraphQL Bangkok Meetup 2.0
GraphQL Bangkok Meetup 2.0
Tobias Meixner
 
Functional Reactive Programming with RxJS
Functional Reactive Programming with RxJSFunctional Reactive Programming with RxJS
Functional Reactive Programming with RxJS
stefanmayer13
 
LSFMM 2019 BPF Observability
LSFMM 2019 BPF ObservabilityLSFMM 2019 BPF Observability
LSFMM 2019 BPF Observability
Brendan Gregg
 
Avoiding Callback Hell with Async.js
Avoiding Callback Hell with Async.jsAvoiding Callback Hell with Async.js
Avoiding Callback Hell with Async.js
cacois
 
Tools for Making Machine Learning more Reactive
Tools for Making Machine Learning more ReactiveTools for Making Machine Learning more Reactive
Tools for Making Machine Learning more Reactive
Jeff Smith
 
Think Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSThink Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJS
Adam L Barrett
 

Similar to JS Fest 2019. Anjana Vakil. Serverless Bebop (20)

Lambdas puzzler - Peter Lawrey
Lambdas puzzler - Peter LawreyLambdas puzzler - Peter Lawrey
Lambdas puzzler - Peter Lawrey
 
RxJava applied [JavaDay Kyiv 2016]
RxJava applied [JavaDay Kyiv 2016]RxJava applied [JavaDay Kyiv 2016]
RxJava applied [JavaDay Kyiv 2016]
 
Compose Async with RxJS
Compose Async with RxJSCompose Async with RxJS
Compose Async with RxJS
 
MongoDB World 2019: Life In Stitch-es
MongoDB World 2019: Life In Stitch-esMongoDB World 2019: Life In Stitch-es
MongoDB World 2019: Life In Stitch-es
 
Expert JavaScript tricks of the masters
Expert JavaScript  tricks of the mastersExpert JavaScript  tricks of the masters
Expert JavaScript tricks of the masters
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node js
 
Developing web-apps like it's 2013
Developing web-apps like it's 2013Developing web-apps like it's 2013
Developing web-apps like it's 2013
 
Wprowadzenie do technologii Big Data / Intro to Big Data Ecosystem
Wprowadzenie do technologii Big Data / Intro to Big Data EcosystemWprowadzenie do technologii Big Data / Intro to Big Data Ecosystem
Wprowadzenie do technologii Big Data / Intro to Big Data Ecosystem
 
Wprowadzenie do technologi Big Data i Apache Hadoop
Wprowadzenie do technologi Big Data i Apache HadoopWprowadzenie do technologi Big Data i Apache Hadoop
Wprowadzenie do technologi Big Data i Apache Hadoop
 
用 Go 語言打造多台機器 Scale 架構
用 Go 語言打造多台機器 Scale 架構用 Go 語言打造多台機器 Scale 架構
用 Go 語言打造多台機器 Scale 架構
 
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
 
Coding Ajax
Coding AjaxCoding Ajax
Coding Ajax
 
The Return of JavaScript: 3 Open-Source Projects that are driving JavaScript'...
The Return of JavaScript: 3 Open-Source Projects that are driving JavaScript'...The Return of JavaScript: 3 Open-Source Projects that are driving JavaScript'...
The Return of JavaScript: 3 Open-Source Projects that are driving JavaScript'...
 
Analytics with Spark
Analytics with SparkAnalytics with Spark
Analytics with Spark
 
GraphQL Bangkok Meetup 2.0
GraphQL Bangkok Meetup 2.0GraphQL Bangkok Meetup 2.0
GraphQL Bangkok Meetup 2.0
 
Functional Reactive Programming with RxJS
Functional Reactive Programming with RxJSFunctional Reactive Programming with RxJS
Functional Reactive Programming with RxJS
 
LSFMM 2019 BPF Observability
LSFMM 2019 BPF ObservabilityLSFMM 2019 BPF Observability
LSFMM 2019 BPF Observability
 
Avoiding Callback Hell with Async.js
Avoiding Callback Hell with Async.jsAvoiding Callback Hell with Async.js
Avoiding Callback Hell with Async.js
 
Tools for Making Machine Learning more Reactive
Tools for Making Machine Learning more ReactiveTools for Making Machine Learning more Reactive
Tools for Making Machine Learning more Reactive
 
Think Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSThink Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJS
 

More from JSFestUA

JS Fest 2019/Autumn. Роман Савіцький. Webcomponents & lit-element in production
JS Fest 2019/Autumn. Роман Савіцький. Webcomponents & lit-element in productionJS Fest 2019/Autumn. Роман Савіцький. Webcomponents & lit-element in production
JS Fest 2019/Autumn. Роман Савіцький. Webcomponents & lit-element in production
JSFestUA
 
JS Fest 2019/Autumn. Erick Wendel. 10 secrets to improve Javascript Performance
JS Fest 2019/Autumn. Erick Wendel. 10 secrets to improve Javascript PerformanceJS Fest 2019/Autumn. Erick Wendel. 10 secrets to improve Javascript Performance
JS Fest 2019/Autumn. Erick Wendel. 10 secrets to improve Javascript Performance
JSFestUA
 
JS Fest 2019/Autumn. Alexandre Gomes. Embrace the "react fatigue"
JS Fest 2019/Autumn. Alexandre Gomes. Embrace the "react fatigue"JS Fest 2019/Autumn. Alexandre Gomes. Embrace the "react fatigue"
JS Fest 2019/Autumn. Alexandre Gomes. Embrace the "react fatigue"
JSFestUA
 
JS Fest 2019/Autumn. Anton Cherednikov. Choreographic or orchestral architect...
JS Fest 2019/Autumn. Anton Cherednikov. Choreographic or orchestral architect...JS Fest 2019/Autumn. Anton Cherednikov. Choreographic or orchestral architect...
JS Fest 2019/Autumn. Anton Cherednikov. Choreographic or orchestral architect...
JSFestUA
 
JS Fest 2019/Autumn. Adam Leos. So why do you need to know Algorithms and Dat...
JS Fest 2019/Autumn. Adam Leos. So why do you need to know Algorithms and Dat...JS Fest 2019/Autumn. Adam Leos. So why do you need to know Algorithms and Dat...
JS Fest 2019/Autumn. Adam Leos. So why do you need to know Algorithms and Dat...
JSFestUA
 
JS Fest 2019/Autumn. Marko Letic. Saving the world with JavaScript: A Data Vi...
JS Fest 2019/Autumn. Marko Letic. Saving the world with JavaScript: A Data Vi...JS Fest 2019/Autumn. Marko Letic. Saving the world with JavaScript: A Data Vi...
JS Fest 2019/Autumn. Marko Letic. Saving the world with JavaScript: A Data Vi...
JSFestUA
 
JS Fest 2019/Autumn. Александр Товмач. JAMstack
JS Fest 2019/Autumn. Александр Товмач. JAMstackJS Fest 2019/Autumn. Александр Товмач. JAMstack
JS Fest 2019/Autumn. Александр Товмач. JAMstack
JSFestUA
 
JS Fest 2019/Autumn. Влад Федосов. Technology agnostic microservices at SPA f...
JS Fest 2019/Autumn. Влад Федосов. Technology agnostic microservices at SPA f...JS Fest 2019/Autumn. Влад Федосов. Technology agnostic microservices at SPA f...
JS Fest 2019/Autumn. Влад Федосов. Technology agnostic microservices at SPA f...
JSFestUA
 
JS Fest 2019/Autumn. Дмитрий Жарков. Blockchainize your SPA or Integrate Java...
JS Fest 2019/Autumn. Дмитрий Жарков. Blockchainize your SPA or Integrate Java...JS Fest 2019/Autumn. Дмитрий Жарков. Blockchainize your SPA or Integrate Java...
JS Fest 2019/Autumn. Дмитрий Жарков. Blockchainize your SPA or Integrate Java...
JSFestUA
 
JS Fest 2019/Autumn. Maciej Treder. Angular Schematics - Develop for developers
JS Fest 2019/Autumn. Maciej Treder. Angular Schematics - Develop for developersJS Fest 2019/Autumn. Maciej Treder. Angular Schematics - Develop for developers
JS Fest 2019/Autumn. Maciej Treder. Angular Schematics - Develop for developers
JSFestUA
 
JS Fest 2019/Autumn. Kyle Boss. A Tinder Love Story: Create a Wordpress Blog ...
JS Fest 2019/Autumn. Kyle Boss. A Tinder Love Story: Create a Wordpress Blog ...JS Fest 2019/Autumn. Kyle Boss. A Tinder Love Story: Create a Wordpress Blog ...
JS Fest 2019/Autumn. Kyle Boss. A Tinder Love Story: Create a Wordpress Blog ...
JSFestUA
 
JS Fest 2019/Autumn. Андрей Старовойт. Зачем нужен тип "true" в TypeScript?
JS Fest 2019/Autumn. Андрей Старовойт. Зачем нужен тип "true" в TypeScript?JS Fest 2019/Autumn. Андрей Старовойт. Зачем нужен тип "true" в TypeScript?
JS Fest 2019/Autumn. Андрей Старовойт. Зачем нужен тип "true" в TypeScript?
JSFestUA
 
JS Fest 2019/Autumn. Eyal Eizenberg. Tipping the Scale
JS Fest 2019/Autumn. Eyal Eizenberg. Tipping the ScaleJS Fest 2019/Autumn. Eyal Eizenberg. Tipping the Scale
JS Fest 2019/Autumn. Eyal Eizenberg. Tipping the Scale
JSFestUA
 
JS Fest 2019/Autumn. Sota Ohara. Сreate own server less CMS from scratch
JS Fest 2019/Autumn. Sota Ohara. Сreate own server less CMS from scratchJS Fest 2019/Autumn. Sota Ohara. Сreate own server less CMS from scratch
JS Fest 2019/Autumn. Sota Ohara. Сreate own server less CMS from scratch
JSFestUA
 
JS Fest 2019/Autumn. Джордж Евтушенко. Как стать программистом, которого хотят
JS Fest 2019/Autumn. Джордж Евтушенко. Как стать программистом, которого хотятJS Fest 2019/Autumn. Джордж Евтушенко. Как стать программистом, которого хотят
JS Fest 2019/Autumn. Джордж Евтушенко. Как стать программистом, которого хотят
JSFestUA
 
JS Fest 2019/Autumn. Алексей Орленко. Node.js N-API for Rust
JS Fest 2019/Autumn. Алексей Орленко. Node.js N-API for RustJS Fest 2019/Autumn. Алексей Орленко. Node.js N-API for Rust
JS Fest 2019/Autumn. Алексей Орленко. Node.js N-API for Rust
JSFestUA
 
JS Fest 2019/Autumn. Daniel Ostrovsky. Falling in love with decorators ES6/Ty...
JS Fest 2019/Autumn. Daniel Ostrovsky. Falling in love with decorators ES6/Ty...JS Fest 2019/Autumn. Daniel Ostrovsky. Falling in love with decorators ES6/Ty...
JS Fest 2019/Autumn. Daniel Ostrovsky. Falling in love with decorators ES6/Ty...
JSFestUA
 
JS Fest 2019/Autumn. Андрей Андрийко. Гексагональна архітектура в Nodejs проекті
JS Fest 2019/Autumn. Андрей Андрийко. Гексагональна архітектура в Nodejs проектіJS Fest 2019/Autumn. Андрей Андрийко. Гексагональна архітектура в Nodejs проекті
JS Fest 2019/Autumn. Андрей Андрийко. Гексагональна архітектура в Nodejs проекті
JSFestUA
 
JS Fest 2019/Autumn. Борис Могила. Svelte. Почему нам не нужно run-time ядро
JS Fest 2019/Autumn. Борис Могила. Svelte. Почему нам не нужно run-time ядроJS Fest 2019/Autumn. Борис Могила. Svelte. Почему нам не нужно run-time ядро
JS Fest 2019/Autumn. Борис Могила. Svelte. Почему нам не нужно run-time ядро
JSFestUA
 
JS Fest 2019/Autumn. Виталий Кухар. Сравнение кластеризации HTTP, TCP и UDP н...
JS Fest 2019/Autumn. Виталий Кухар. Сравнение кластеризации HTTP, TCP и UDP н...JS Fest 2019/Autumn. Виталий Кухар. Сравнение кластеризации HTTP, TCP и UDP н...
JS Fest 2019/Autumn. Виталий Кухар. Сравнение кластеризации HTTP, TCP и UDP н...
JSFestUA
 

More from JSFestUA (20)

JS Fest 2019/Autumn. Роман Савіцький. Webcomponents & lit-element in production
JS Fest 2019/Autumn. Роман Савіцький. Webcomponents & lit-element in productionJS Fest 2019/Autumn. Роман Савіцький. Webcomponents & lit-element in production
JS Fest 2019/Autumn. Роман Савіцький. Webcomponents & lit-element in production
 
JS Fest 2019/Autumn. Erick Wendel. 10 secrets to improve Javascript Performance
JS Fest 2019/Autumn. Erick Wendel. 10 secrets to improve Javascript PerformanceJS Fest 2019/Autumn. Erick Wendel. 10 secrets to improve Javascript Performance
JS Fest 2019/Autumn. Erick Wendel. 10 secrets to improve Javascript Performance
 
JS Fest 2019/Autumn. Alexandre Gomes. Embrace the "react fatigue"
JS Fest 2019/Autumn. Alexandre Gomes. Embrace the "react fatigue"JS Fest 2019/Autumn. Alexandre Gomes. Embrace the "react fatigue"
JS Fest 2019/Autumn. Alexandre Gomes. Embrace the "react fatigue"
 
JS Fest 2019/Autumn. Anton Cherednikov. Choreographic or orchestral architect...
JS Fest 2019/Autumn. Anton Cherednikov. Choreographic or orchestral architect...JS Fest 2019/Autumn. Anton Cherednikov. Choreographic or orchestral architect...
JS Fest 2019/Autumn. Anton Cherednikov. Choreographic or orchestral architect...
 
JS Fest 2019/Autumn. Adam Leos. So why do you need to know Algorithms and Dat...
JS Fest 2019/Autumn. Adam Leos. So why do you need to know Algorithms and Dat...JS Fest 2019/Autumn. Adam Leos. So why do you need to know Algorithms and Dat...
JS Fest 2019/Autumn. Adam Leos. So why do you need to know Algorithms and Dat...
 
JS Fest 2019/Autumn. Marko Letic. Saving the world with JavaScript: A Data Vi...
JS Fest 2019/Autumn. Marko Letic. Saving the world with JavaScript: A Data Vi...JS Fest 2019/Autumn. Marko Letic. Saving the world with JavaScript: A Data Vi...
JS Fest 2019/Autumn. Marko Letic. Saving the world with JavaScript: A Data Vi...
 
JS Fest 2019/Autumn. Александр Товмач. JAMstack
JS Fest 2019/Autumn. Александр Товмач. JAMstackJS Fest 2019/Autumn. Александр Товмач. JAMstack
JS Fest 2019/Autumn. Александр Товмач. JAMstack
 
JS Fest 2019/Autumn. Влад Федосов. Technology agnostic microservices at SPA f...
JS Fest 2019/Autumn. Влад Федосов. Technology agnostic microservices at SPA f...JS Fest 2019/Autumn. Влад Федосов. Technology agnostic microservices at SPA f...
JS Fest 2019/Autumn. Влад Федосов. Technology agnostic microservices at SPA f...
 
JS Fest 2019/Autumn. Дмитрий Жарков. Blockchainize your SPA or Integrate Java...
JS Fest 2019/Autumn. Дмитрий Жарков. Blockchainize your SPA or Integrate Java...JS Fest 2019/Autumn. Дмитрий Жарков. Blockchainize your SPA or Integrate Java...
JS Fest 2019/Autumn. Дмитрий Жарков. Blockchainize your SPA or Integrate Java...
 
JS Fest 2019/Autumn. Maciej Treder. Angular Schematics - Develop for developers
JS Fest 2019/Autumn. Maciej Treder. Angular Schematics - Develop for developersJS Fest 2019/Autumn. Maciej Treder. Angular Schematics - Develop for developers
JS Fest 2019/Autumn. Maciej Treder. Angular Schematics - Develop for developers
 
JS Fest 2019/Autumn. Kyle Boss. A Tinder Love Story: Create a Wordpress Blog ...
JS Fest 2019/Autumn. Kyle Boss. A Tinder Love Story: Create a Wordpress Blog ...JS Fest 2019/Autumn. Kyle Boss. A Tinder Love Story: Create a Wordpress Blog ...
JS Fest 2019/Autumn. Kyle Boss. A Tinder Love Story: Create a Wordpress Blog ...
 
JS Fest 2019/Autumn. Андрей Старовойт. Зачем нужен тип "true" в TypeScript?
JS Fest 2019/Autumn. Андрей Старовойт. Зачем нужен тип "true" в TypeScript?JS Fest 2019/Autumn. Андрей Старовойт. Зачем нужен тип "true" в TypeScript?
JS Fest 2019/Autumn. Андрей Старовойт. Зачем нужен тип "true" в TypeScript?
 
JS Fest 2019/Autumn. Eyal Eizenberg. Tipping the Scale
JS Fest 2019/Autumn. Eyal Eizenberg. Tipping the ScaleJS Fest 2019/Autumn. Eyal Eizenberg. Tipping the Scale
JS Fest 2019/Autumn. Eyal Eizenberg. Tipping the Scale
 
JS Fest 2019/Autumn. Sota Ohara. Сreate own server less CMS from scratch
JS Fest 2019/Autumn. Sota Ohara. Сreate own server less CMS from scratchJS Fest 2019/Autumn. Sota Ohara. Сreate own server less CMS from scratch
JS Fest 2019/Autumn. Sota Ohara. Сreate own server less CMS from scratch
 
JS Fest 2019/Autumn. Джордж Евтушенко. Как стать программистом, которого хотят
JS Fest 2019/Autumn. Джордж Евтушенко. Как стать программистом, которого хотятJS Fest 2019/Autumn. Джордж Евтушенко. Как стать программистом, которого хотят
JS Fest 2019/Autumn. Джордж Евтушенко. Как стать программистом, которого хотят
 
JS Fest 2019/Autumn. Алексей Орленко. Node.js N-API for Rust
JS Fest 2019/Autumn. Алексей Орленко. Node.js N-API for RustJS Fest 2019/Autumn. Алексей Орленко. Node.js N-API for Rust
JS Fest 2019/Autumn. Алексей Орленко. Node.js N-API for Rust
 
JS Fest 2019/Autumn. Daniel Ostrovsky. Falling in love with decorators ES6/Ty...
JS Fest 2019/Autumn. Daniel Ostrovsky. Falling in love with decorators ES6/Ty...JS Fest 2019/Autumn. Daniel Ostrovsky. Falling in love with decorators ES6/Ty...
JS Fest 2019/Autumn. Daniel Ostrovsky. Falling in love with decorators ES6/Ty...
 
JS Fest 2019/Autumn. Андрей Андрийко. Гексагональна архітектура в Nodejs проекті
JS Fest 2019/Autumn. Андрей Андрийко. Гексагональна архітектура в Nodejs проектіJS Fest 2019/Autumn. Андрей Андрийко. Гексагональна архітектура в Nodejs проекті
JS Fest 2019/Autumn. Андрей Андрийко. Гексагональна архітектура в Nodejs проекті
 
JS Fest 2019/Autumn. Борис Могила. Svelte. Почему нам не нужно run-time ядро
JS Fest 2019/Autumn. Борис Могила. Svelte. Почему нам не нужно run-time ядроJS Fest 2019/Autumn. Борис Могила. Svelte. Почему нам не нужно run-time ядро
JS Fest 2019/Autumn. Борис Могила. Svelte. Почему нам не нужно run-time ядро
 
JS Fest 2019/Autumn. Виталий Кухар. Сравнение кластеризации HTTP, TCP и UDP н...
JS Fest 2019/Autumn. Виталий Кухар. Сравнение кластеризации HTTP, TCP и UDP н...JS Fest 2019/Autumn. Виталий Кухар. Сравнение кластеризации HTTP, TCP и UDP н...
JS Fest 2019/Autumn. Виталий Кухар. Сравнение кластеризации HTTP, TCP и UDP н...
 

Recently uploaded

Oliver Asks for More by Charles Dickens (9)
Oliver Asks for More by Charles Dickens (9)Oliver Asks for More by Charles Dickens (9)
Oliver Asks for More by Charles Dickens (9)
nitinpv4ai
 
Educational Technology in the Health Sciences
Educational Technology in the Health SciencesEducational Technology in the Health Sciences
Educational Technology in the Health Sciences
Iris Thiele Isip-Tan
 
Leveraging Generative AI to Drive Nonprofit Innovation
Leveraging Generative AI to Drive Nonprofit InnovationLeveraging Generative AI to Drive Nonprofit Innovation
Leveraging Generative AI to Drive Nonprofit Innovation
TechSoup
 
Benner "Expanding Pathways to Publishing Careers"
Benner "Expanding Pathways to Publishing Careers"Benner "Expanding Pathways to Publishing Careers"
Benner "Expanding Pathways to Publishing Careers"
National Information Standards Organization (NISO)
 
RESULTS OF THE EVALUATION QUESTIONNAIRE.pptx
RESULTS OF THE EVALUATION QUESTIONNAIRE.pptxRESULTS OF THE EVALUATION QUESTIONNAIRE.pptx
RESULTS OF THE EVALUATION QUESTIONNAIRE.pptx
zuzanka
 
HYPERTENSION - SLIDE SHARE PRESENTATION.
HYPERTENSION - SLIDE SHARE PRESENTATION.HYPERTENSION - SLIDE SHARE PRESENTATION.
HYPERTENSION - SLIDE SHARE PRESENTATION.
deepaannamalai16
 
Level 3 NCEA - NZ: A Nation In the Making 1872 - 1900 SML.ppt
Level 3 NCEA - NZ: A  Nation In the Making 1872 - 1900 SML.pptLevel 3 NCEA - NZ: A  Nation In the Making 1872 - 1900 SML.ppt
Level 3 NCEA - NZ: A Nation In the Making 1872 - 1900 SML.ppt
Henry Hollis
 
BÀI TẬP DẠY THÊM TIẾNG ANH LỚP 7 CẢ NĂM FRIENDS PLUS SÁCH CHÂN TRỜI SÁNG TẠO ...
BÀI TẬP DẠY THÊM TIẾNG ANH LỚP 7 CẢ NĂM FRIENDS PLUS SÁCH CHÂN TRỜI SÁNG TẠO ...BÀI TẬP DẠY THÊM TIẾNG ANH LỚP 7 CẢ NĂM FRIENDS PLUS SÁCH CHÂN TRỜI SÁNG TẠO ...
BÀI TẬP DẠY THÊM TIẾNG ANH LỚP 7 CẢ NĂM FRIENDS PLUS SÁCH CHÂN TRỜI SÁNG TẠO ...
Nguyen Thanh Tu Collection
 
BIOLOGY NATIONAL EXAMINATION COUNCIL (NECO) 2024 PRACTICAL MANUAL.pptx
BIOLOGY NATIONAL EXAMINATION COUNCIL (NECO) 2024 PRACTICAL MANUAL.pptxBIOLOGY NATIONAL EXAMINATION COUNCIL (NECO) 2024 PRACTICAL MANUAL.pptx
BIOLOGY NATIONAL EXAMINATION COUNCIL (NECO) 2024 PRACTICAL MANUAL.pptx
RidwanHassanYusuf
 
REASIGNACION 2024 UGEL CHUPACA 2024 UGEL CHUPACA.pdf
REASIGNACION 2024 UGEL CHUPACA 2024 UGEL CHUPACA.pdfREASIGNACION 2024 UGEL CHUPACA 2024 UGEL CHUPACA.pdf
REASIGNACION 2024 UGEL CHUPACA 2024 UGEL CHUPACA.pdf
giancarloi8888
 
How to deliver Powerpoint Presentations.pptx
How to deliver Powerpoint  Presentations.pptxHow to deliver Powerpoint  Presentations.pptx
How to deliver Powerpoint Presentations.pptx
HajraNaeem15
 
MDP on air pollution of class 8 year 2024-2025
MDP on air pollution of class 8 year 2024-2025MDP on air pollution of class 8 year 2024-2025
MDP on air pollution of class 8 year 2024-2025
khuleseema60
 
skeleton System.pdf (skeleton system wow)
skeleton System.pdf (skeleton system wow)skeleton System.pdf (skeleton system wow)
skeleton System.pdf (skeleton system wow)
Mohammad Al-Dhahabi
 
Data Structure using C by Dr. K Adisesha .ppsx
Data Structure using C by Dr. K Adisesha .ppsxData Structure using C by Dr. K Adisesha .ppsx
Data Structure using C by Dr. K Adisesha .ppsx
Prof. Dr. K. Adisesha
 
THE SACRIFICE HOW PRO-PALESTINE PROTESTS STUDENTS ARE SACRIFICING TO CHANGE T...
THE SACRIFICE HOW PRO-PALESTINE PROTESTS STUDENTS ARE SACRIFICING TO CHANGE T...THE SACRIFICE HOW PRO-PALESTINE PROTESTS STUDENTS ARE SACRIFICING TO CHANGE T...
THE SACRIFICE HOW PRO-PALESTINE PROTESTS STUDENTS ARE SACRIFICING TO CHANGE T...
indexPub
 
Wound healing PPT
Wound healing PPTWound healing PPT
Wound healing PPT
Jyoti Chand
 
Temple of Asclepius in Thrace. Excavation results
Temple of Asclepius in Thrace. Excavation resultsTemple of Asclepius in Thrace. Excavation results
Temple of Asclepius in Thrace. Excavation results
Krassimira Luka
 
CIS 4200-02 Group 1 Final Project Report (1).pdf
CIS 4200-02 Group 1 Final Project Report (1).pdfCIS 4200-02 Group 1 Final Project Report (1).pdf
CIS 4200-02 Group 1 Final Project Report (1).pdf
blueshagoo1
 
Présentationvvvvvvvvvvvvvvvvvvvvvvvvvvvv2.pptx
Présentationvvvvvvvvvvvvvvvvvvvvvvvvvvvv2.pptxPrésentationvvvvvvvvvvvvvvvvvvvvvvvvvvvv2.pptx
Présentationvvvvvvvvvvvvvvvvvvvvvvvvvvvv2.pptx
siemaillard
 
Haunted Houses by H W Longfellow for class 10
Haunted Houses by H W Longfellow for class 10Haunted Houses by H W Longfellow for class 10
Haunted Houses by H W Longfellow for class 10
nitinpv4ai
 

Recently uploaded (20)

Oliver Asks for More by Charles Dickens (9)
Oliver Asks for More by Charles Dickens (9)Oliver Asks for More by Charles Dickens (9)
Oliver Asks for More by Charles Dickens (9)
 
Educational Technology in the Health Sciences
Educational Technology in the Health SciencesEducational Technology in the Health Sciences
Educational Technology in the Health Sciences
 
Leveraging Generative AI to Drive Nonprofit Innovation
Leveraging Generative AI to Drive Nonprofit InnovationLeveraging Generative AI to Drive Nonprofit Innovation
Leveraging Generative AI to Drive Nonprofit Innovation
 
Benner "Expanding Pathways to Publishing Careers"
Benner "Expanding Pathways to Publishing Careers"Benner "Expanding Pathways to Publishing Careers"
Benner "Expanding Pathways to Publishing Careers"
 
RESULTS OF THE EVALUATION QUESTIONNAIRE.pptx
RESULTS OF THE EVALUATION QUESTIONNAIRE.pptxRESULTS OF THE EVALUATION QUESTIONNAIRE.pptx
RESULTS OF THE EVALUATION QUESTIONNAIRE.pptx
 
HYPERTENSION - SLIDE SHARE PRESENTATION.
HYPERTENSION - SLIDE SHARE PRESENTATION.HYPERTENSION - SLIDE SHARE PRESENTATION.
HYPERTENSION - SLIDE SHARE PRESENTATION.
 
Level 3 NCEA - NZ: A Nation In the Making 1872 - 1900 SML.ppt
Level 3 NCEA - NZ: A  Nation In the Making 1872 - 1900 SML.pptLevel 3 NCEA - NZ: A  Nation In the Making 1872 - 1900 SML.ppt
Level 3 NCEA - NZ: A Nation In the Making 1872 - 1900 SML.ppt
 
BÀI TẬP DẠY THÊM TIẾNG ANH LỚP 7 CẢ NĂM FRIENDS PLUS SÁCH CHÂN TRỜI SÁNG TẠO ...
BÀI TẬP DẠY THÊM TIẾNG ANH LỚP 7 CẢ NĂM FRIENDS PLUS SÁCH CHÂN TRỜI SÁNG TẠO ...BÀI TẬP DẠY THÊM TIẾNG ANH LỚP 7 CẢ NĂM FRIENDS PLUS SÁCH CHÂN TRỜI SÁNG TẠO ...
BÀI TẬP DẠY THÊM TIẾNG ANH LỚP 7 CẢ NĂM FRIENDS PLUS SÁCH CHÂN TRỜI SÁNG TẠO ...
 
BIOLOGY NATIONAL EXAMINATION COUNCIL (NECO) 2024 PRACTICAL MANUAL.pptx
BIOLOGY NATIONAL EXAMINATION COUNCIL (NECO) 2024 PRACTICAL MANUAL.pptxBIOLOGY NATIONAL EXAMINATION COUNCIL (NECO) 2024 PRACTICAL MANUAL.pptx
BIOLOGY NATIONAL EXAMINATION COUNCIL (NECO) 2024 PRACTICAL MANUAL.pptx
 
REASIGNACION 2024 UGEL CHUPACA 2024 UGEL CHUPACA.pdf
REASIGNACION 2024 UGEL CHUPACA 2024 UGEL CHUPACA.pdfREASIGNACION 2024 UGEL CHUPACA 2024 UGEL CHUPACA.pdf
REASIGNACION 2024 UGEL CHUPACA 2024 UGEL CHUPACA.pdf
 
How to deliver Powerpoint Presentations.pptx
How to deliver Powerpoint  Presentations.pptxHow to deliver Powerpoint  Presentations.pptx
How to deliver Powerpoint Presentations.pptx
 
MDP on air pollution of class 8 year 2024-2025
MDP on air pollution of class 8 year 2024-2025MDP on air pollution of class 8 year 2024-2025
MDP on air pollution of class 8 year 2024-2025
 
skeleton System.pdf (skeleton system wow)
skeleton System.pdf (skeleton system wow)skeleton System.pdf (skeleton system wow)
skeleton System.pdf (skeleton system wow)
 
Data Structure using C by Dr. K Adisesha .ppsx
Data Structure using C by Dr. K Adisesha .ppsxData Structure using C by Dr. K Adisesha .ppsx
Data Structure using C by Dr. K Adisesha .ppsx
 
THE SACRIFICE HOW PRO-PALESTINE PROTESTS STUDENTS ARE SACRIFICING TO CHANGE T...
THE SACRIFICE HOW PRO-PALESTINE PROTESTS STUDENTS ARE SACRIFICING TO CHANGE T...THE SACRIFICE HOW PRO-PALESTINE PROTESTS STUDENTS ARE SACRIFICING TO CHANGE T...
THE SACRIFICE HOW PRO-PALESTINE PROTESTS STUDENTS ARE SACRIFICING TO CHANGE T...
 
Wound healing PPT
Wound healing PPTWound healing PPT
Wound healing PPT
 
Temple of Asclepius in Thrace. Excavation results
Temple of Asclepius in Thrace. Excavation resultsTemple of Asclepius in Thrace. Excavation results
Temple of Asclepius in Thrace. Excavation results
 
CIS 4200-02 Group 1 Final Project Report (1).pdf
CIS 4200-02 Group 1 Final Project Report (1).pdfCIS 4200-02 Group 1 Final Project Report (1).pdf
CIS 4200-02 Group 1 Final Project Report (1).pdf
 
Présentationvvvvvvvvvvvvvvvvvvvvvvvvvvvv2.pptx
Présentationvvvvvvvvvvvvvvvvvvvvvvvvvvvv2.pptxPrésentationvvvvvvvvvvvvvvvvvvvvvvvvvvvv2.pptx
Présentationvvvvvvvvvvvvvvvvvvvvvvvvvvvv2.pptx
 
Haunted Houses by H W Longfellow for class 10
Haunted Houses by H W Longfellow for class 10Haunted Houses by H W Longfellow for class 10
Haunted Houses by H W Longfellow for class 10
 

JS Fest 2019. Anjana Vakil. Serverless Bebop

  • 1. from Big Band Web App to Serverless Bebop @AnjanaVakil JazzCon.Tech 2018
  • 2. Hello! I’m @AnjanaVakil Recurse Center Non-Graduate Mozilla TechSpeaker & Outreachy Alumna Engineering Learning & Development Lead, Mapbox
  • 3. location data platform for developers maps, search, navigation web, iOS, Android, Unity... @AnjanaVakil JazzCon.Tech 2018
  • 5. we use to ◍ get user stats ◍ monitor/test unpacker uploads ◍ ask yoda who’s on call ◍ see who’s out tmrw ◍ pick a random teammate Place your screenshot here @AnjanaVakil JazzCon.Tech 2018
  • 7. codebase slack-commands/ ├─ readme.md ├─ cloudformation/ #app & cmd config │ └─ slack-commands.template.js ├─ index.js #express app ├─ commands/ │ ├─ out.js │ ├─ stats.js │ └─ ... └─ test/ ├─ index.test.js ├─ out.test.js ├─ stats.test.js └─ ... @AnjanaVakil JazzCon.Tech 2018
  • 8. All commands in a single app: Downsides Security ◍ Permissions? Secrets? ◍ Least privilege Maintenance ◍ Many different teams involved ◍ Ownership? Support? ◍ Code gumbo Cost ◍ Always running ◍ No per-command breakdown @AnjanaVakil JazzCon.Tech 2018
  • 9. enough about computers let’s talk about jazz @AnjanaVakil JazzCon.Tech 2018
  • 10. “ While swing music tended to feature orchestrated big band arrangements, bebop music highlighted improvisation. @AnjanaVakil JazzCon.Tech 2018 wikipedia
  • 11. Big Band Glenn Miller Orchestra, c. 1940
  • 12. Big Band out unpacker status yoda Express slack i/o auth user- limits @AnjanaVakil JazzCon.Tech 2018
  • 13. “I kept thinking there's bound to be something else. I could hear it sometimes. I couldn't play it.... I found that by using the higher intervals of a chord as a melody line and backing them with appropriately related changes, I could play the thing I'd been hearing. It came alive. - Charlie Parker @AnjanaVakil JazzCon.Tech 2018 wikipedia
  • 14. Bebop Tommy Potter, Charlie Parker, Max Roach, Miles Davis, & Duke Jordan, NYC c. 1945
  • 15. “As bebop was not intended for dancing, it enabled the musicians to play at faster tempos. Bebop musicians explored advanced harmonies, complex syncopation, altered chords, extended chords, chord substitutions, asymmetrical phrasing, and intricate melodies. @AnjanaVakil JazzCon.Tech 2018 wikipedia
  • 17. “there’s bound to be something else” ◍ Assign a single owner/gatekeeper? ◍ Multiple single-command apps? ◍ Separate commands from router app @AnjanaVakil JazzCon.Tech 2018
  • 18. “serverless” functions to the rescue AWS Lambda @AnjanaVakil JazzCon.Tech 2018
  • 19. what do you mean “serverless” Actual Server You own a computer You put code on it You run it constantly (and you pay constantly) You keep it healthy Cloud Server AWS owns a computer (or 2) You put code on it AWS runs it constantly (and you pay constantly) You tell AWS how to keep it healthy “No” Server AWS owns a computer You put code on it AWS runs it when you ask (and you pay only then) AWS keeps it healthy @AnjanaVakil JazzCon.Tech 2018
  • 20. ◍ Only concern: Input -> Output ◍ No state maintained between calls ◍ Can be side-effecting, though (e.g. API call, database write) ◍ Limited resources & exec time (5m) what do you mean “function” @AnjanaVakil JazzCon.Tech 2018
  • 21. Lose the server if it’s... ◍ small ◍ short-lived ◍ self-contained ◍ needed occasionally to lambda or not to lambda Keep the server if it’s... ◍ heavy ◍ long-running ◍ interdependent ◍ needed constantly @AnjanaVakil JazzCon.Tech 2018
  • 22. HTTP API endpoint AWS load balancerEC2s on ECS JS JSJS old architecture @AnjanaVakil JazzCon.Tech 2018
  • 24. old codebase slack-commands/ ├─ readme.md ├─ cloudformation/ #app & cmd config │ └─ slack-commands.template.js ├─ index.js #express app code ├─ commands/ #cmd code │ ├─ out.js │ ├─ stats.js │ └─ ... └─ test/ #app & cmd tests ├─ index.test.js ├─ out.test.js ├─ stats.test.js └─ ... @AnjanaVakil JazzCon.Tech 2018
  • 25. new codebase slack-commands/ ├─ readme.md ├─ cloudformation/ #app config │ └─ slack-commands.template.js ├─ index.js #express app code ├─ commander.js #invoke lambdas └─ test/ ├─ commander.test.js └─ index.test.js slack-command-{cmd}/ ├ readme.md ├ cloudformation/ #cmd config │ └ slack-command-{cmd}.template.js ├ index.js #cmd code └ test/ └ index.test.js@AnjanaVakil JazzCon.Tech 2018
  • 26. what does a function look like? @AnjanaVakil JazzCon.Tech 2018
  • 27. Place your screenshot here user stats commmand @AnjanaVakil JazzCon.Tech 2018
  • 28. module.exports.command = (event, context, callback) => { const { ApiCoreUrl, MapboxToken } = process.env; const user = event.args[0]; const from = new Date(event.args[1] || (+new Date - 864e5*30)); // 30d const to = new Date(event.args[2] || (+new Date)); if (isNaN(from)||isNaN(to)) return callback(new Error('invalid date')); const requrl = getStatsUrl(user, from, to, ApiCoreUrl, MapboxToken); request(requrl, (err, res, body) => { if (err||res.statusCode !== 200) return callback(err||res.statusCode); try { const data = JSON.parse(body); } catch(err) { return callback(err); } return callback(null, formatStatsMessage(user, data)); }); } @AnjanaVakil JazzCon.Tech 2018
  • 29. module.exports.command = (event, context, callback) => { const { ApiCoreUrl, MapboxToken } = process.env; const user = event.args[0]; const from = new Date(event.args[1] || (+new Date - 864e5*30)); // 30d const to = new Date(event.args[2] || (+new Date)); if (isNaN(from)||isNaN(to)) return callback(new Error('invalid date')); const requrl = getStatsUrl(user, from, to, ApiCoreUrl, MapboxToken); request(requrl, (err, res, body) => { if (err||res.statusCode !== 200) return callback(err||res.statusCode); try { const data = JSON.parse(body); } catch(err) { return callback(err); } return callback(null, formatStatsMessage(user, data)); }); } handler function (we tell Lambda its name) @AnjanaVakil JazzCon.Tech 2018
  • 30. module.exports.command = (event, context, callback) => { const { ApiCoreUrl, MapboxToken } = process.env; const user = event.args[0]; const from = new Date(event.args[1] || (+new Date - 864e5*30)); // 30d const to = new Date(event.args[2] || (+new Date)); if (isNaN(from)||isNaN(to)) return callback(new Error('invalid date')); const requrl = getStatsUrl(user, from, to, ApiCoreUrl, MapboxToken); request(requrl, (err, res, body) => { if (err||res.statusCode !== 200) return callback(err||res.statusCode); try { const data = JSON.parse(body); } catch(err) { return callback(err); } return callback(null, formatStatsMessage(user, data)); }); } execution environment we can configure @AnjanaVakil JazzCon.Tech 2018
  • 31. module.exports.command = (event, context, callback) => { const { ApiCoreUrl, MapboxToken } = process.env; const user = event.args[0]; const from = new Date(event.args[1] || (+new Date - 864e5*30)); // 30d const to = new Date(event.args[2] || (+new Date)); if (isNaN(from)||isNaN(to)) return callback(new Error('invalid date')); const requrl = getStatsUrl(user, from, to, ApiCoreUrl, MapboxToken); request(requrl, (err, res, body) => { if (err||res.statusCode !== 200) return callback(err||res.statusCode); try { const data = JSON.parse(body); } catch(err) { return callback(err); } return callback(null, formatStatsMessage(user, data)); }); } input { args: [ “vakila”, “1/1”, “3/22”] } @AnjanaVakil JazzCon.Tech 2018
  • 32. module.exports.command = (event, context, callback) => { const { ApiCoreUrl, MapboxToken } = process.env; const user = event.args[0]; const from = new Date(event.args[1] || (+new Date - 864e5*30)); // 30d const to = new Date(event.args[2] || (+new Date)); if (isNaN(from)||isNaN(to)) return callback(new Error('invalid date')); const requrl = getStatsUrl(user, from, to, ApiCoreUrl, MapboxToken); request(requrl, (err, res, body) => { if (err||res.statusCode !== 200) return callback(err||res.statusCode); try { const data = JSON.parse(body); } catch(err) { return callback(err); } return callback(null, formatStatsMessage(user, data)); }); } aws runtime info (e.g. time remaining - ignored here) @AnjanaVakil JazzCon.Tech 2018
  • 33. module.exports.command = (event, context, callback) => { const { ApiCoreUrl, MapboxToken } = process.env; const user = event.args[0]; const from = new Date(event.args[1] || (+new Date - 864e5*30)); // 30d const to = new Date(event.args[2] || (+new Date)); if (isNaN(from)||isNaN(to)) return callback(new Error('invalid date')); const requrl = getStatsUrl(user, from, to, ApiCoreUrl, MapboxToken); request(requrl, (err, res, body) => { if (err||res.statusCode !== 200) return callback(err||res.statusCode); try { const data = JSON.parse(body); } catch(err) { return callback(err); } return callback(null, formatStatsMessage(user, data)); }); } “ok, I’m done” function (AWS passes this when executing) error data @AnjanaVakil JazzCon.Tech 2018
  • 34. we wrote a function! yay @AnjanaVakil JazzCon.Tech 2018
  • 35. do we get it up there? how @AnjanaVakil JazzCon.Tech 2018
  • 36. Cloud::Formation templates ◍ JSON template - “just code” ◍ define your AWS stack components ◍ upload -> AWS builds your stack @AnjanaVakil JazzCon.Tech 2018
  • 37. Cloud::Formation templates { "AWSTemplateFormatVersion": "2010-09-09", "Description": "slack-command-stats", "Parameters": { "ApiCoreUrl": {...}, "MapboxToken": {...} "Resources": { "Command": { "Type": "AWS::Lambda::Function", "Properties": {...} }, "CommandRole": { "Type": "AWS::IAM::Role", "Properties": {...} } }, "Outputs": { ... } } @AnjanaVakil JazzCon.Tech 2018
  • 38. Cloud::Formation templates { "AWSTemplateFormatVersion": "2010-09-09", "Description": "slack-command-stats", "Parameters": { "ApiCoreUrl": {...}, "MapboxToken": {...} "Resources": { "Command": { "Type": "AWS::Lambda::Function", "Properties": {...} }, "CommandRole": { "Type": "AWS::IAM::Role", "Properties": {...} } }, "Outputs": { ... } } stack input params @AnjanaVakil JazzCon.Tech 2018
  • 39. Cloud::Formation templates { "AWSTemplateFormatVersion": "2010-09-09", "Description": "slack-command-stats", "Parameters": { "ApiCoreUrl": {...}, "MapboxToken": {...} "Resources": { "Command": { "Type": "AWS::Lambda::Function", "Properties": {...} }, "CommandRole": { "Type": "AWS::IAM::Role", "Properties": {...} } }, "Outputs": { ... } } aws permissions for function @AnjanaVakil JazzCon.Tech 2018
  • 40. Cloud::Formation templates { "AWSTemplateFormatVersion": "2010-09-09", "Description": "slack-command-stats", "Parameters": { "ApiCoreUrl": {...}, "MapboxToken": {...} "Resources": { "Command": { "Type": "AWS::Lambda::Function", "Properties": {...} }, "CommandRole": { "Type": "AWS::IAM::Role", "Properties": {...} } }, "Outputs": { ... } } actual lambda function the good stuff @AnjanaVakil JazzCon.Tech 2018
  • 41. Cloud::Formation templates "Command": { "Type": "AWS::Lambda::Function", "Properties": { "FunctionName": "slack-command-stats-production", "Code": { "S3Bucket": {...}, "S3Key": {...} }, "Handler": "index.command", "Environment": { "Variables": { "ApiCoreUrl": { "Ref": "ApiCoreUrl" }, "MapboxToken": { "Ref": "MapboxToken" } } }, "Role": { "Fn::GetAtt": ["CommandRole","Arn"] }, "Runtime": "nodejs4.3", "MemorySize": 128, "Timeout": 60, "Tags": [ { "Key": "Team", "Value": "EngOps"} ] } } @AnjanaVakil JazzCon.Tech 2018
  • 42. Cloud::Formation templates "Command": { "Type": "AWS::Lambda::Function", "Properties": { "FunctionName": "slack-command-stats-production", "Code": { "S3Bucket": {...}, "S3Key": {...} }, "Handler": "index.command", "Environment": { "Variables": { "ApiCoreUrl": { "Ref": "ApiCoreUrl" }, "MapboxToken": { "Ref": "MapboxToken" } } }, "Role": { "Fn::GetAtt": ["CommandRole","Arn"] }, "Runtime": "nodejs4.3", "MemorySize": 128, "Timeout": 60, "Tags": [ { "Key": "Team", "Value": "EngOps"} ] } } @AnjanaVakil JazzCon.Tech 2018 function name helps find it later
  • 43. Cloud::Formation templates "Command": { "Type": "AWS::Lambda::Function", "Properties": { "FunctionName": "slack-command-stats-production", "Code": { "S3Bucket": {...}, "S3Key": {...} }, "Handler": "index.command", "Environment": { "Variables": { "ApiCoreUrl": { "Ref": "ApiCoreUrl" }, "MapboxToken": { "Ref": "MapboxToken" } } }, "Role": { "Fn::GetAtt": ["CommandRole","Arn"] }, "Runtime": "nodejs4.3", "MemorySize": 128, "Timeout": 60, "Tags": [ { "Key": "Team", "Value": "EngOps"} ] } } @AnjanaVakil JazzCon.Tech 2018 code to run the good stuff
  • 44. Cloud::Formation templates "Command": { "Type": "AWS::Lambda::Function", "Properties": { "FunctionName": "slack-command-stats-production", "Code": { "S3Bucket": {...}, "S3Key": {...} }, "Handler": "index.command", "Environment": { "Variables": { "ApiCoreUrl": { "Ref": "ApiCoreUrl" }, "MapboxToken": { "Ref": "MapboxToken" } } }, "Role": { "Fn::GetAtt": ["CommandRole","Arn"] }, "Runtime": "nodejs4.3", "MemorySize": 128, "Timeout": 60, "Tags": [ { "Key": "Team", "Value": "EngOps"} ] } } @AnjanaVakil JazzCon.Tech 2018 execution environment can pass in params
  • 45. Cloud::Formation templates "Command": { "Type": "AWS::Lambda::Function", "Properties": { "FunctionName": "slack-command-stats-production", "Code": { "S3Bucket": {...}, "S3Key": {...} }, "Handler": "index.command", "Environment": { "Variables": { "ApiCoreUrl": { "Ref": "ApiCoreUrl" }, "MapboxToken": { "Ref": "MapboxToken" } } }, "Role": { "Fn::GetAtt": ["CommandRole","Arn"] }, "Runtime": "nodejs4.3", "MemorySize": 128, "Timeout": 60, "Tags": [ { "Key": "Team", "Value": "EngOps"} ] } } @AnjanaVakil JazzCon.Tech 2018 permissions from earlier
  • 46. Cloud::Formation templates "Command": { "Type": "AWS::Lambda::Function", "Properties": { "FunctionName": "slack-command-stats-production", "Code": { "S3Bucket": {...}, "S3Key": {...} }, "Handler": "index.command", "Environment": { "Variables": { "ApiCoreUrl": { "Ref": "ApiCoreUrl" }, "MapboxToken": { "Ref": "MapboxToken" } } }, "Role": { "Fn::GetAtt": ["CommandRole","Arn"] }, "Runtime": "nodejs4.3", "MemorySize": 128, "Timeout": 60, "Tags": [ { "Key": "Team", "Value": "EngOps"} ] } } @AnjanaVakil JazzCon.Tech 2018 what to run it on totally not a server
  • 47. Cloud::Formation templates "Command": { "Type": "AWS::Lambda::Function", "Properties": { "FunctionName": "slack-command-stats-production", "Code": { "S3Bucket": {...}, "S3Key": {...} }, "Handler": "index.command", "Environment": { "Variables": { "ApiCoreUrl": { "Ref": "ApiCoreUrl" }, "MapboxToken": { "Ref": "MapboxToken" } } }, "Role": { "Fn::GetAtt": ["CommandRole","Arn"] }, "Runtime": "nodejs4.3", "MemorySize": 128, "Timeout": 60, "Tags": [ { "Key": "Team", "Value": "EngOps"} ] } } @AnjanaVakil JazzCon.Tech 2018 arbitrary tags e.g. who owns this?
  • 48. Mapbox open-source AWS helpers github.com/mapbox/ Command-line tools lambda-cfn create & deploy Node Lambda functions cfn-config configure/start/update CFN stacks JS libraries cloudfriend easily assemble CFN templates in JS decrypt-kms-env use secret environment vars @AnjanaVakil JazzCon.Tech 2018
  • 49. we deployed a function! yay @AnjanaVakil JazzCon.Tech 2018
  • 50. do we call it? how @AnjanaVakil JazzCon.Tech 2018
  • 51. testing in the AWS console (manually) @AnjanaVakil JazzCon.Tech 2018
  • 52. in Node with AWS SDK const AWS = require('aws-sdk'); const runCommand = (req, res, next) => { const [commandName, ...args] = = req.slackText; const params = { FunctionName: `slack-command-${commandName}-production`, // our convention Payload: JSON.stringify({ args: args }), // the `event` Lambda receives }; const lambda = new AWS.Lambda({ region: 'us-east-1' }); lambda.invoke(params).promise() .catch((err) => err.message) // pass on error message as response data .then((data) => res.json(formatForSlack(data))); }; @AnjanaVakil JazzCon.Tech 2018
  • 53. why did we do all that? @AnjanaVakil JazzCon.Tech 2018
  • 54. Before (single app) ◍ Many secrets in one stack ◍ Updating your code updates whole stack ◍ No fine-grained cost analysis Refactoring to Lambda: Benefits After (multiple Lambdas) ◍ Each stack only knows its own secrets ◍ Updating your code leaves others untouched ◍ Each stack/fn can be tagged & cost-monitored @AnjanaVakil JazzCon.Tech 2018
  • 57. Merci! @AnjanaVakil anjana@mapbox.com ✌ Team Mapbox Young Hahn, Emily McAfee, Kelly Young, Jake Pruitt, Andrew Evans JazzCon.Tech Organizers Images from Wikimedia Template by SlidesCarnival.com