{"id":1351,"date":"2017-10-10T11:14:48","date_gmt":"2017-10-10T11:14:48","guid":{"rendered":"https:\/\/gosqeng.test\/?p=1351"},"modified":"2019-11-28T11:13:57","modified_gmt":"2019-11-28T11:13:57","slug":"lambda-edge","status":"publish","type":"post","link":"https:\/\/www.gosquared.com\/blog\/lambda-edge","title":{"rendered":"Lambda@Edge: putting Serverless even closer to your users"},"content":{"rendered":"<p><img decoding=\"async\" src=\"https:\/\/static.gosquared.com\/images\/liquidicity\/17_10_09_lambda_01@2x.jpg\" alt=\"Lambda at Edge illustration\"\/><\/p>\n<p>Lambda@Edge was first announced in preview by AWS <a href=\"https:\/\/aws.amazon.com\/blogs\/aws\/coming-soon-lambda-at-the-edge\/\" target=\"_blank\" rel=\"noopener noreferrer\">back in December<\/a>; it hit public release <a href=\"https:\/\/aws.amazon.com\/blogs\/aws\/lambdaedge-intelligent-processing-of-http-requests-at-the-edge\/\" target=\"_blank\" rel=\"noopener noreferrer\">in July<\/a>. We\u2019ve been using it since the preview &#8211; here\u2019s some of the things we\u2019ve learned along the way.<\/p>\n<h2>What is Lambda@Edge?<\/h2>\n<p>Lambda is AWS\u2019s \u201cserverless\u201d platform for running code as functions &#8211; instead of booting EC2 Instances (i.e. \u201cservers\u201d) and worrying about operating systems, supervisors, logging, deployment, scaling, or any of the other factors required to actually run your code, you can simply write the code for a function in your favourite programming language (JavaScript, Python, Java or C#), and AWS will take care of the undifferentiated heavy lifting of actually getting that code to run somewhere.<\/p>\n<p>CloudFront is AWS\u2019s content delivery network (CDN), which acts as a layer on top of your web site or assets, for distributing your content globally, so that assets (typically JavaScript, CSS or images) can be cached and served from a point of presence (or \u201cedge location\u201d) geographically close to your users. You can put CloudFront in front of any web origin you like, most commonly either web servers of your own or hooked directly into an S3 bucket.<\/p>\n<p>Typically with a CDN like CloudFront, web content falls into two categories: static and dynamic. Static content includes assets like JavaScript or images which are the same no matter who is requesting them or how; dynamic content includes parts of your web site or app that vary based on application logic &#8211; whether or not the user is logged in etc.<\/p>\n<p>In most cases you\u2019ll set up your CDN to cache static content so it\u2019s always readily-available at the edge closest to your user and doesn\u2019t need re-fetching. Dynamic content, since by definition it\u2019s not constant, can\u2019t be cached, and the CDN has to hit your origin server for those requests. This extra request back to the origin adds extra latency, and effectively negates the benefit of having a CDN in the first place.<\/p>\n<p>What Lambda@Edge allows you to do is to push some of the dynamic logic from your origin onto CloudFront\u2019s edge servers. You can write some code, deploy it to Lambda@Edge, and have it interact with requests from your visitors at the edge location, geographically close to your users, potentially enabling you to serve some of your dynamic content requirements without incurring the full round-trip latency to your origin server.<\/p>\n<p>There are some restrictions to exactly what you can implement with Lambda@Edge &#8211; you get a very limited amount of resources, so reimplementing your entire application\u2019s logic at the edge probably isn\u2019t feasible &#8211; but there is a wide variety of simple cases in which Lambda@Edge can help you move logic closer to your users, reducing latency and creating a faster experience.<\/p>\n<h2>How does it work?<\/h2>\n<p><img decoding=\"async\" src=\"https:\/\/static.gosquared.com\/images\/liquidicity\/17_10_09_lambda_02@2x.jpg\" alt=\"Lambda at Edge illustration\"\/><\/p>\n<p>Lambda@Edge effectively allows you to hook into requests as they pass through the CloudFront edge servers, and modify data in flight. There are four different stages in the request lifecycle that you can hook into: viewer request, which comes immediately after the request is received by the edge server, before hitting the cache layer; origin request which come when the edge server has decided it needs to fetch data from the origin server, but before it sends the request; origin response after the origin has sent its response, but before the response gets cached; and viewer response which is called on every request just before the response is sent to your user\u2019s browser. <\/p>\n<p>At each of these stages the request\/response body and headers can be modified. Your Lambda function can also call out to external sources of data to inject directly into the content. Additionally, either of the request hooks can be used to directly generate a response rather than letting the request continue to the cache or origin server.<\/p>\n<h3>Viewer vs. Origin handlers<\/h3>\n<p>There\u2019s an important distinction between the viewer and the origin handlers described above: the viewer handlers will be called for every single request received by the CloudFront distribution, before any caching behaviour. This is useful if, for example, you want to perform an A\/B test based on a cookie value by modifying the requested URL, but it\u2019s important to bear in mind that these functions come with a (small) overhead that will add to the overall latency of the request. The origin handlers, on the other hand, are only called when the CloudFront edge does not have the requested content in the cache, or decides that the content needs to be refreshed. So if the modifications you are making to requests or responses can be cached and reused, the origin handlers may be more appropriate.<\/p>\n<h2>What can I do with this?<\/h2>\n<p>There are an endless number of possible things that can be achieved with Lambda@Edge, and here at GoSquared we\u2019ve barely scratched the surface. But here are our favourite two use-cases:<\/p>\n<h3>Adding security headers on S3 origins<\/h3>\n<p>One of the best things about CloudFront since its inception is its support for plugging directly into S3 for serving static assets. You can simply put CloudFront in front of an S3 bucket and have it serve all the objects within it, without having to worry about setting up any web servers of your own.<\/p>\n<p>The downside that comes with S3 origins is that S3 doesn\u2019t give you a huge amount of control over exactly how those objects are served &#8211; most notably the HTTP headers sent along with the response data.<\/p>\n<p>Many browser security features are controlled by HTTP headers such as <code>Access-Control-Allow-Origin<\/code>, <code>Content-Security-Policy<\/code> and <code>Strict-Transport-Security<\/code>, so being able to set these headers on all your resources and assets is essential nowadays. With Lambda@Edge it\u2019s now a simple matter of adding an origin response handler to add or modify these headers before the response gets stored in the cache.<\/p>\n<p>We\u2019ve also found the fine-grained programmatic control allowed by Lambda@Edge to be useful purely for neatness as well as security. The deploy process we use for some of our S3 assets leaves useful metadata attached to these assets, which are served up as <code>X-Amz-Meta-*<\/code> headers. This metadata is useful for us and our deployments, but serves no value to the end-user, so we take advantage of Lambda@Edge to clean up these headers from being sent out.<\/p>\n<p>Here\u2019s an example of a Lambda@Edge origin response handler we might have for this sort of header-modification.<\/p>\n<pre class=\"language-javascript\"><code>exports.handler = (event, context, callback) => {\n  const headers = event.Records[0].cf.response.headers;\n\n  \/\/ Strip out unnecessary metadata headers\n  Object.keys(headers).forEach(k => {\n    if (\/^x-amz-meta\/i.test(k)) {\n      delete headers[k];\n    }\n  });\n\n  function setHeader(k, v) {\n    headers[k.toLowerCase()] = [ { key: k, value: v } ];\n  }\n\n  setHeader('Access-Control-Allow-Credentials', 'true');\n  setHeader('Access-Control-Allow-Origin', '*');\n  setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET');\n  setHeader('Access-Control-Allow-Headers', 'Content-Type, Depth, User-Agent, X-File-Size, X-Requested-With, If-Modified-Since, X-File-Name, Cache-Control, Cookie');\n  setHeader('Strict-Transport-Security', 'max-age=31536000');\n  setHeader('X-XSS-Protection', '1; mode=block');\n  setHeader('Cache-Control', 'public, max-age=86400');\n\n  callback(null, event.Records[0].cf.response);\n};\n<\/code><\/pre>\n<p>Previously we would use a tier of web servers in between the S3 origin and CloudFront to perform all this header-modification logic. Now we can offload everything to Lambda@Edge and completely remove a whole moving part from the flow. Woo serverless!<\/p>\n<h3>Serving pre-compressed versions of files<\/h3>\n<p>In the original days of CloudFront, it did not support any kind of modification to your response data at all. This included modifications such as using gzip Content-Encoding to reduce bandwidth. This was fine if you were using an origin server which supported dynamically serving compressed or uncompressed content based on the <code>Accept-Encoding<\/code> request header. The one small problem with this was that S3 didn\u2019t support dynamic compression like this.<\/p>\n<p><a href=\"https:\/\/aws.amazon.com\/blogs\/aws\/new-gzip-compression-support-for-amazon-cloudfront\/\" target=\"_blank\" rel=\"noopener noreferrer\">Back in December 2015<\/a> CloudFront added support for gzip compression at the edge, which solved this problem for the most part. But here at GoSquared we had additional needs.<\/p>\n<p>The gzip compression algorithm can be tweaked based on how heavily you want data compressed. This comes with a tradeoff where better compression (i.e. fewer output bytes) usually uses more processing power. If this compression is happening on every request then usually you choose a compression level that strikes a balance between low bandwidth and low server load. However, CloudFront doesn\u2019t allow you to choose the compression level for automatic edge compression.<\/p>\n<p>The benefit of static content, though, is that if it doesn\u2019t change very often, then the compressed version also doesn\u2019t change very often. That means that if you\u2019re able to pre-compress all your content ahead-of-time, you can dial all the numbers up to maximum and not worry about any per-request overhead. And with more recent gzip-compatible algorithms like <a href=\"https:\/\/github.com\/google\/zopfli\" target=\"_blank\" rel=\"noopener noreferrer\">Zopfli<\/a>, it\u2019s actually possible to save a noticeable amount of bandwidth, albeit with a comparatively large (often huge) amount of upfront CPU usage.<\/p>\n<p>For most use-cases this won\u2019t make much of a difference, but for certain very-frequently-accessed assets, such as GoSquared\u2019s JavaScript tracking snippet, which is accessed billions of times every month, a 4-5% reduction in bandwidth adds up to a noticeable cost.<\/p>\n<p>The way we go about this is to generate two versions of every file at build-time: the normal, uncompressed version, and a gzip-compatible compressed version, generated using zopfli with maximum compression settings. We then use an origin request handler to rewrite the requested object URL based on the <code>Accept-Encoding<\/code> header:<\/p>\n<pre class=\"language-javascript\"><code>exports.handler = (event, context, callback) => {\n  const request = event.Records[0].cf.request;\n  const headers = request.headers;\n\n  let gz = false;\n\n  const ae = headers['accept-encoding'];\n  if (ae) {\n    for (let i = 0; i < ae.length; i++) {\n      const value = ae[i].value;\n      const bits = value.split(',').map(x => x.split(';')[0].trim());\n      if (bits.indexOf('gzip') !== -1) {\n        gz = true;\n      }\n    }\n  }\n\n  \/\/ If gzip is supported, use the pre-compressed version of the file,\n  \/\/ which is the same URL with .gz on the end\n  if (gz) request.uri += '.gz';\n    \n  callback(null, request);\n};\n<\/code><\/pre>\n<p><em>Cheeky side-note if anyone at AWS is reading this<\/em>: we\u2019d love to be able to use this technique to support alternative compression algorithms like brotli, but CloudFront currently rewrites the <code>Accept-Encoding<\/code> header to strip out anything other than <code>gzip<\/code>. Consider this a feature request?<\/p>\n<h2>What else can Lambda@Edge do?<\/h2>\n<p>Our own use-cases for Lambda@Edge mostly take advantage of the origin request and response handlers, but there are endless possibilities for other powerful uses of Lambda@Edge. <\/p>\n<p>For example, a viewer request handler can be used for issuing redirects in front of a static S3 site (we currently have a tier of nginx web servers for handling redirects for old URLs, Lambda@Edge would allow that logic to be offloaded to CloudFront).<\/p>\n<p>Another example would be to use a viewer response handler to modify the content of a response based on parameters that aren\u2019t relevant to the cache behaviour. For example, you may have an image asset that you want to serve with a <code>Content-Disposition<\/code> header if a <code>?download=true<\/code> query-string parameter is present, but allowing CloudFront cache differently based on query string parameters would be inefficient.<\/p>\n<h2>How are you using Lambda@Edge?<\/h2>\n<p>Are you using Lambda@Edge yourself? Do you have an even better use-case that we haven\u2019t thought of yet? Let us know!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Lambda@Edge was first announced in preview by AWS back in December; it hit public release in July. We\u2019ve been using&#8230;<\/p>\n","protected":false},"author":5,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1452],"tags":[93,119,1579],"class_list":["post-1351","post","type-post","status-publish","format-standard","hentry","category-engineering","tag-amazon","tag-aws","tag-web-services"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v18.6 (Yoast SEO v19.0) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Lambda@Edge: putting Serverless even closer to your users - GoSquared Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.gosquared.com\/blog\/lambda-edge\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Lambda@Edge: putting Serverless even closer to your users\" \/>\n<meta property=\"og:description\" content=\"Lambda@Edge was first announced in preview by AWS back in December; it hit public release in July. We\u2019ve been using...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.gosquared.com\/blog\/lambda-edge\" \/>\n<meta property=\"og:site_name\" content=\"GoSquared Blog\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/GoSquared\" \/>\n<meta property=\"article:published_time\" content=\"2017-10-10T11:14:48+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2019-11-28T11:13:57+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/static.gosquared.com\/images\/liquidicity\/17_10_09_lambda_twitter_01@2x.jpg\" \/>\n<meta name=\"twitter:creator\" content=\"@floopily\" \/>\n<meta name=\"twitter:site\" content=\"@GoSquared\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"JT\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.gosquared.com\/blog\/#organization\",\"name\":\"GoSquared\",\"url\":\"https:\/\/www.gosquared.com\/blog\/\",\"sameAs\":[\"https:\/\/instagram.com\/gosquaredteam\",\"https:\/\/www.linkedin.com\/company\/go-squared-ltd.\",\"https:\/\/www.facebook.com\/GoSquared\",\"https:\/\/twitter.com\/GoSquared\"],\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.gosquared.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.gosquared.com\/blog\/wp-content\/uploads\/2015\/07\/gosquared.png\",\"contentUrl\":\"https:\/\/www.gosquared.com\/blog\/wp-content\/uploads\/2015\/07\/gosquared.png\",\"width\":1270,\"height\":250,\"caption\":\"GoSquared\"},\"image\":{\"@id\":\"https:\/\/www.gosquared.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.gosquared.com\/blog\/#website\",\"url\":\"https:\/\/www.gosquared.com\/blog\/\",\"name\":\"GoSquared Blog\",\"description\":\"Turn visitors into customers.\",\"publisher\":{\"@id\":\"https:\/\/www.gosquared.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.gosquared.com\/blog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.gosquared.com\/blog\/lambda-edge#primaryimage\",\"url\":\"\",\"contentUrl\":\"\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.gosquared.com\/blog\/lambda-edge#webpage\",\"url\":\"https:\/\/www.gosquared.com\/blog\/lambda-edge\",\"name\":\"Lambda@Edge: putting Serverless even closer to your users - GoSquared Blog\",\"isPartOf\":{\"@id\":\"https:\/\/www.gosquared.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.gosquared.com\/blog\/lambda-edge#primaryimage\"},\"datePublished\":\"2017-10-10T11:14:48+00:00\",\"dateModified\":\"2019-11-28T11:13:57+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.gosquared.com\/blog\/lambda-edge#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.gosquared.com\/blog\/lambda-edge\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.gosquared.com\/blog\/lambda-edge#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.gosquared.com\/blog\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Lambda@Edge: putting Serverless even closer to your users\"}]},{\"@type\":\"Article\",\"@id\":\"https:\/\/www.gosquared.com\/blog\/lambda-edge#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.gosquared.com\/blog\/lambda-edge#webpage\"},\"author\":{\"@id\":\"https:\/\/www.gosquared.com\/blog\/#\/schema\/person\/bfcd35bf2eba92ecbeea67937cd23eef\"},\"headline\":\"Lambda@Edge: putting Serverless even closer to your users\",\"datePublished\":\"2017-10-10T11:14:48+00:00\",\"dateModified\":\"2019-11-28T11:13:57+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.gosquared.com\/blog\/lambda-edge#webpage\"},\"wordCount\":1705,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.gosquared.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.gosquared.com\/blog\/lambda-edge#primaryimage\"},\"thumbnailUrl\":\"\",\"keywords\":[\"Amazon\",\"AWS\",\"Web Services\"],\"articleSection\":[\"Engineering\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.gosquared.com\/blog\/lambda-edge#respond\"]}]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.gosquared.com\/blog\/#\/schema\/person\/bfcd35bf2eba92ecbeea67937cd23eef\",\"name\":\"JT\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.gosquared.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/772e026206b900a5ba17ebbe63e34a4c8a9103524cf0ba3accfa38b14d7d03ba?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/772e026206b900a5ba17ebbe63e34a4c8a9103524cf0ba3accfa38b14d7d03ba?s=96&d=mm&r=g\",\"caption\":\"JT\"},\"description\":\"JT is a co-founder and the lead front-end engineer at GoSquared. He's responsible for the shiniest of the shiny projects we work on.\",\"sameAs\":[\"https:\/\/twitter.com\/floopily\"],\"url\":\"https:\/\/www.gosquared.com\/blog\/author\/jt\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Lambda@Edge: putting Serverless even closer to your users - GoSquared Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.gosquared.com\/blog\/lambda-edge","og_locale":"en_US","og_type":"article","og_title":"Lambda@Edge: putting Serverless even closer to your users","og_description":"Lambda@Edge was first announced in preview by AWS back in December; it hit public release in July. We\u2019ve been using...","og_url":"https:\/\/www.gosquared.com\/blog\/lambda-edge","og_site_name":"GoSquared Blog","article_publisher":"https:\/\/www.facebook.com\/GoSquared","article_published_time":"2017-10-10T11:14:48+00:00","article_modified_time":"2019-11-28T11:13:57+00:00","twitter_card":"summary_large_image","twitter_image":"https:\/\/static.gosquared.com\/images\/liquidicity\/17_10_09_lambda_twitter_01@2x.jpg","twitter_creator":"@floopily","twitter_site":"@GoSquared","twitter_misc":{"Written by":"JT","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Organization","@id":"https:\/\/www.gosquared.com\/blog\/#organization","name":"GoSquared","url":"https:\/\/www.gosquared.com\/blog\/","sameAs":["https:\/\/instagram.com\/gosquaredteam","https:\/\/www.linkedin.com\/company\/go-squared-ltd.","https:\/\/www.facebook.com\/GoSquared","https:\/\/twitter.com\/GoSquared"],"logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.gosquared.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.gosquared.com\/blog\/wp-content\/uploads\/2015\/07\/gosquared.png","contentUrl":"https:\/\/www.gosquared.com\/blog\/wp-content\/uploads\/2015\/07\/gosquared.png","width":1270,"height":250,"caption":"GoSquared"},"image":{"@id":"https:\/\/www.gosquared.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"WebSite","@id":"https:\/\/www.gosquared.com\/blog\/#website","url":"https:\/\/www.gosquared.com\/blog\/","name":"GoSquared Blog","description":"Turn visitors into customers.","publisher":{"@id":"https:\/\/www.gosquared.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.gosquared.com\/blog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.gosquared.com\/blog\/lambda-edge#primaryimage","url":"","contentUrl":""},{"@type":"WebPage","@id":"https:\/\/www.gosquared.com\/blog\/lambda-edge#webpage","url":"https:\/\/www.gosquared.com\/blog\/lambda-edge","name":"Lambda@Edge: putting Serverless even closer to your users - GoSquared Blog","isPartOf":{"@id":"https:\/\/www.gosquared.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.gosquared.com\/blog\/lambda-edge#primaryimage"},"datePublished":"2017-10-10T11:14:48+00:00","dateModified":"2019-11-28T11:13:57+00:00","breadcrumb":{"@id":"https:\/\/www.gosquared.com\/blog\/lambda-edge#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.gosquared.com\/blog\/lambda-edge"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.gosquared.com\/blog\/lambda-edge#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.gosquared.com\/blog"},{"@type":"ListItem","position":2,"name":"Lambda@Edge: putting Serverless even closer to your users"}]},{"@type":"Article","@id":"https:\/\/www.gosquared.com\/blog\/lambda-edge#article","isPartOf":{"@id":"https:\/\/www.gosquared.com\/blog\/lambda-edge#webpage"},"author":{"@id":"https:\/\/www.gosquared.com\/blog\/#\/schema\/person\/bfcd35bf2eba92ecbeea67937cd23eef"},"headline":"Lambda@Edge: putting Serverless even closer to your users","datePublished":"2017-10-10T11:14:48+00:00","dateModified":"2019-11-28T11:13:57+00:00","mainEntityOfPage":{"@id":"https:\/\/www.gosquared.com\/blog\/lambda-edge#webpage"},"wordCount":1705,"commentCount":0,"publisher":{"@id":"https:\/\/www.gosquared.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.gosquared.com\/blog\/lambda-edge#primaryimage"},"thumbnailUrl":"","keywords":["Amazon","AWS","Web Services"],"articleSection":["Engineering"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.gosquared.com\/blog\/lambda-edge#respond"]}]},{"@type":"Person","@id":"https:\/\/www.gosquared.com\/blog\/#\/schema\/person\/bfcd35bf2eba92ecbeea67937cd23eef","name":"JT","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.gosquared.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/772e026206b900a5ba17ebbe63e34a4c8a9103524cf0ba3accfa38b14d7d03ba?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/772e026206b900a5ba17ebbe63e34a4c8a9103524cf0ba3accfa38b14d7d03ba?s=96&d=mm&r=g","caption":"JT"},"description":"JT is a co-founder and the lead front-end engineer at GoSquared. He's responsible for the shiniest of the shiny projects we work on.","sameAs":["https:\/\/twitter.com\/floopily"],"url":"https:\/\/www.gosquared.com\/blog\/author\/jt"}]}},"wps_subtitle":"And how to use it to kill all your web servers","_links":{"self":[{"href":"https:\/\/www.gosquared.com\/blog\/wp-json\/wp\/v2\/posts\/1351","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.gosquared.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gosquared.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gosquared.com\/blog\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gosquared.com\/blog\/wp-json\/wp\/v2\/comments?post=1351"}],"version-history":[{"count":0,"href":"https:\/\/www.gosquared.com\/blog\/wp-json\/wp\/v2\/posts\/1351\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.gosquared.com\/blog\/wp-json\/wp\/v2\/media?parent=1351"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gosquared.com\/blog\/wp-json\/wp\/v2\/categories?post=1351"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gosquared.com\/blog\/wp-json\/wp\/v2\/tags?post=1351"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}