{"componentChunkName":"component---node-modules-gatsby-theme-medium-to-own-blog-src-templates-blog-post-js","path":"/things-about-serverless-i-wish-i-used-from-the-start/","result":{"data":{"site":{"siteMetadata":{"siteUrl":"https://javame.netlify.app","githubUrl":"https://github.com/aterreno/blog"}},"mdx":{"fields":{"slug":"/things-about-serverless-i-wish-i-used-from-the-start/"},"excerpt":"This list comes from the time ‘wasted’ going through multiple git repositories, changing, pushing, one by one all the serverless.yml file…","timeToRead":2,"frontmatter":{"title":"Things about serverless I wish I used from the start","description":"This list comes from the time ‘wasted’ going through multiple git repositories, changing, pushing, one by one all the serverless.yml file…","categories":[],"date":"February 22, 2019","canonical_link":"https://javame.netlify.app//things-about-serverless-i-wish-i-used-from-the-start-edd3841d6a95"},"body":"function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"title\": \"Things about serverless I wish I used from the start\",\n  \"description\": \"This list comes from the time ‘wasted’ going through multiple git repositories, changing, pushing, one by one all the serverless.yml file…\",\n  \"date\": \"2019-02-22T16:57:22.988Z\",\n  \"categories\": [],\n  \"published\": true,\n  \"canonical_link\": \"https://javame.netlify.app//things-about-serverless-i-wish-i-used-from-the-start-edd3841d6a95\",\n  \"redirect_from\": [\"/things-about-serverless-i-wish-i-used-from-the-start-edd3841d6a95\"]\n};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, [\"components\"]);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, \"This list comes from the time \\u2018wasted\\u2019 going through multiple git repositories, changing, pushing, one by one all the serverless.yml file, making \\u2018horizontal change\\u2019 across all functions: if I knew these things existed when I started, I would have saved myself quite some time\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {}), \"${ssm:variable}\\n\")), mdx(\"p\", null, \"You can use \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-paramstore.html\",\n    \"target\": \"_blank\",\n    \"rel\": \"nofollow noopener noreferrer\"\n  }), \"SSM Parameter Store\"), \" and it\\u2019s dead easy to use, no more hardcoded variables or secrets, those variables get expanded at build time by Serverless, we started to use them also for not-so-secret stuff, it\\u2019s nice to have a versioned, auditable repository with all those values in AWS.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {}), \"versionFunctions: false\\n\")), mdx(\"p\", null, \"After a few months, we ran out of space on the \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://docs.aws.amazon.com/lambda/latest/dg/limits.html\",\n    \"target\": \"_blank\",\n    \"rel\": \"nofollow noopener noreferrer\"\n  }), \"Function and layer storage\"), \", which is by default 75 GB. I ended up writing a Janitor lambda function to remove all the non-live lambda deployments, but I much rather work with a always roll forward policy, so all our functions now are basically not versioned, something less to worry about.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {}), \"logRetentionInDays: 30\\n\")), mdx(\"p\", null, \"Another parameter that you probably want to specify is the logging retention policy, this will avoid over cluttering (and overpaying) your Cloudwatch bill. 30 days is still probably too much, as we tend to fix whatever is wrong in less than 24 hours.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {}), \"deploymentBucket:\\n    name: your-serverless-lambdas-deployments-bucket\\n\")), mdx(\"p\", null, \"Without setting this parameter things get a bit out of control with randomly generated buckets names, with this, all the deployments will end up in S3 in a nice and tidy structure such as serverless/{service-name}/{stage}.\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {}), \"plugins:\\n  - serverless-log-forwarding\\n\")), mdx(\"p\", null, \"We recently introduced centralised logging, Cloudwatch is far from being usable as logging system, we use \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://www.npmjs.com/package/serverless-log-forwarding\",\n    \"target\": \"_blank\",\n    \"rel\": \"nofollow noopener noreferrer\"\n  }), \"this plugin\"), \" and forward our logs to a lambda that forwards then the logs to \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://papertrailapp.com/\",\n    \"target\": \"_blank\",\n    \"rel\": \"nofollow noopener noreferrer\"\n  }), \"Papertrail\"), \".\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {}), \"custom:\\n  iopipeToken: ${file(${opt:stage}.yml):iopipeToken}\\n\")), mdx(\"p\", null, \"I always mention \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://www.iopipe.com/\",\n    \"target\": \"_blank\",\n    \"rel\": \"nofollow noopener noreferrer\"\n  }), \"IOPipe\"), \" and we used this since the very early days, but what I didn\\u2019t realise until recently is that the free plan offers two projects, so you can actually split your monitoring in prod and non-prod environments and set up what they call \\u2018global\\u2019 alerts: no need to set up a new alert every time you introduce a new lambda.\"), mdx(\"p\", null, \"A last thought: we implemented our lambdas in multiple git repositories, every repository might have from one to fourteen functions each, but what if we were doing a mono repo? We could have one single serverless.yml file, with the common configuration and then many other yml files containing function specific configuration. I think it might work really well, the serverless framework development moves really fast and to fully leverage the plugins system I think it would be easier to embrace a mono-repo structure.\"), mdx(\"p\", null, \"I\\u2019d love to hear what are your favourite, must-have plugins and some war stories on serverless and mono-repos.\"));\n}\n;\nMDXContent.isMDXComponent = true;"},"allWebMentionEntry":{"nodes":[]}},"pageContext":{"id":"2c739b3e-932e-5e1b-b05e-4f0ac8751522","previous":{"id":"3d69d86d-193c-5f75-877d-e588ffac32c0","fields":{"slug":"/startup-pre-series-a-tech-choices-you-can't-compromise-on/","published":true},"frontmatter":{"redirect_from":["/startup-pre-series-a-tech-choices-you-cant-compromise-on-a499a75f3f06"],"redirect_to":null,"title":"Startup Pre-series A tech choices you can’t compromise on"}},"next":{"id":"cd350344-8b7f-5421-88bd-700c5d685178","fields":{"slug":"/experiences-as-an-interviewee/","published":true},"frontmatter":{"redirect_from":["/experiences-as-an-interviewee-28e16131f31a"],"redirect_to":null,"title":"Experiences as an interviewee"}},"permalink":"https://javame.netlify.app/things-about-serverless-i-wish-i-used-from-the-start/","themeOptions":{"plugins":[],"config":{"title":"Antonio Terreno","description":"Antonio Terreno's blog archive","shortBio":"","bio":"Principal Consultant at Equal Experts","author":"Antonio Terreno","githubUrl":"https://github.com/aterreno/blog","siteUrl":"https://javame.netlify.app/","social":{"twitter":"javame","medium":"","facebook":"","github":"aterreno","linkedin":"antonioterreno","instagram":"tritonitri"},"goatCounterCode":null}}}},"staticQueryHashes":["4131332129","645483741"]}