<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Dan</title>
    <description>The latest articles on DEV Community by Dan (@dengel29).</description>
    <link>https://dev.to/dengel29</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F132266%2Fb12aa591-d188-4bb6-8840-be29eabc1cfd.png</url>
      <title>DEV Community: Dan</title>
      <link>https://dev.to/dengel29</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dengel29"/>
    <language>en</language>
    <item>
      <title>Flexible Upsert With DynamoDB</title>
      <dc:creator>Dan</dc:creator>
      <pubDate>Wed, 14 Oct 2020 09:28:31 +0000</pubDate>
      <link>https://dev.to/dengel29/flexible-upsert-with-dynamodb-397j</link>
      <guid>https://dev.to/dengel29/flexible-upsert-with-dynamodb-397j</guid>
      <description>&lt;p&gt;I recently made a switch from Postgres to Dynamodb and have been learning some pretty basic stuff. I’m working with a single table with a single kind of item so none of the tough NoSQL relational paradigm stuff, just some basic putting and updating. In using DynamoDB's built-in &lt;code&gt;update&lt;/code&gt; function, I came across what I imagine is a pretty ordinary case that was not covered in documentation: how to update records allowing any possible combination of properties. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html#Expressions.UpdateExpressions.SET"&gt;Update Expressions from the Amazon DynamoDB docs, for reference&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Case
&lt;/h3&gt;

&lt;p&gt;Here’s the case:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I have an item that I want to insert into my table, that has an arbitrary amount of properties;&lt;/li&gt;
&lt;li&gt;I expect it will be updated, adding to those initial properties &lt;em&gt;another&lt;/em&gt;,  different set of arbitrary properties.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words: I’ll create an item with &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;              properties, and later on will update it with property &lt;code&gt;z&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;I read that the default behavior for DynamoDB’s &lt;code&gt;update&lt;/code&gt; is like Postgres’ &lt;code&gt;UPSERT&lt;/code&gt;, ie  it will create the record in the database if it cannot find it by its primary key. So it sounded like I could do my insert &lt;strong&gt;and&lt;/strong&gt; update logic in the same function, which would be great.&lt;/p&gt;

&lt;p&gt;By its nature, DynamoDB (and NoSQL databases in general, as far as I understand) have the flexibility to create records with any properties. That’s why it was surprising to me that the problem I kept running into was specifically of that nature: DynamoDB &lt;strong&gt;would not&lt;/strong&gt; let me update a record with a property it didn’t already have if I didn’t supply all its other already-existing properties.&lt;/p&gt;

&lt;p&gt;In the most simplified example, this is what was happening:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I create an item with &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; properties;&lt;/li&gt;
&lt;li&gt;I then update that item with &lt;code&gt;z&lt;/code&gt; property;&lt;/li&gt;
&lt;li&gt;The update fails because I did not supply &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;properties. The error message was: "ExpressionAttributeValues cannot be NULL" (if you're new to DynamoDB I cover ExpressionAttributeValues below).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s a good &lt;a href="https://stackoverflow.com/questions/45842363/dynamodb-updateitem-ignore-null-values-in-expressionattributevalues/52157337"&gt;Stack Overflow post&lt;/a&gt; with a similar problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Coding the Problem
&lt;/h3&gt;

&lt;p&gt;In my project, I’m building a database of video games. I want to save some info about each one: &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;developer&lt;/code&gt;, &lt;code&gt;publisher&lt;/code&gt;, &lt;code&gt;releaseDate&lt;/code&gt;, and a lot more. But let’s start simple, with just one attribute. &lt;/p&gt;

&lt;p&gt;In the example below, let’s imagine we have a table where the primary key (&lt;code&gt;Key&lt;/code&gt; below) is the title, and we already have a record in the database that exists with that &lt;code&gt;Key&lt;/code&gt;. This is how we would update a single attribute, &lt;code&gt;developer&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Uncharted&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;developer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Naughty Dog&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;TableName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DYNAMODB_TABLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;UpdateExpression&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SET developer =  :dev&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;ExpressionAttributeValues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;:dev&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;developer&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;dynamodb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So this works, but with this approach, we’ve totally hamstrung the flexibility of DynamoDB. We are expecting a specific bit of data to be sent in with the request, &lt;code&gt;data.developer&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;What happens if we want to add any other properties to this request? Well, if we don’t change the code at all and send a request with, say, a &lt;code&gt;publisher&lt;/code&gt; property in the data with our &lt;code&gt;developer&lt;/code&gt; and &lt;code&gt;title&lt;/code&gt;, it simply won’t get written to the record.  To accommodate new data to add, we'd have to change the &lt;code&gt;UpdateExpression&lt;/code&gt; and the &lt;code&gt;ExpressionAttributeValues&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Uncharted&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;developer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Naughty Dog&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;publisher&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Sony&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;TableName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DYNAMODB_TABLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;UpdateExpression&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SET developer =  :dev&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;publisher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;pub&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;ExpressionAttributeValues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;:dev&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;developer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;:pub&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publisher&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;dynamodb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, this works, but if you ever update your object without &lt;em&gt;every single attribute&lt;/em&gt;, the request will fail with the  &lt;em&gt;ExpressionAttributeValues cannot be NULL&lt;/em&gt; error.  You're not allowed to update &lt;em&gt;just&lt;/em&gt; the developer, or &lt;em&gt;just&lt;/em&gt; the publisher with this approach.&lt;/p&gt;

&lt;p&gt;This completely goes against what I’d read and learned about as one of the main selling points of NoSQL: flexibility. &lt;/p&gt;

&lt;h3&gt;
  
  
  How We Fix It
&lt;/h3&gt;

&lt;p&gt;So looking at the Stack Overflow article I posted above gave me a few ideas that got me to a solution I feel good about.&lt;/p&gt;

&lt;p&gt;If you look at the structure of the params that you actually supply to the &lt;code&gt;dynamodb.update()&lt;/code&gt; function, it’s just a simple object with UpperCamelCased keys. So rather than hardcode the attributes we want to update, we can dynamically build our update function based on whatever attributes have been provided. &lt;/p&gt;

&lt;p&gt;So the key things we need to build are the &lt;code&gt;UpdateExpression&lt;/code&gt; and the &lt;code&gt;ExpressionAttributeValues&lt;/code&gt;.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Programming UpdateExpression
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;UpdateExpression&lt;/code&gt; uses an SQL-like syntax to SET, ADD (increment), or REMOVE certain attributes on the item you’re updating. If you want to SET multiple attributes in a single expression it will look like what we did above:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;SET latestUpdate = :updateTime, developer = :developer, publisher = :publisher&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Those colon-prefixed keys like &lt;code&gt;:updateTime&lt;/code&gt; will be found in the &lt;code&gt;ExpressionAttributeValues&lt;/code&gt;. They're arbitrary placeholders, so name them anything you want as long as they match a value in the &lt;code&gt;ExpressionAttributeValues&lt;/code&gt;. You can think of it as the value substitution (aka "&lt;a href="https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html#defense-option-1-prepared-statements-with-parameterized-queries"&gt;Parameterized Queries&lt;/a&gt;") you find in SQL. &lt;/p&gt;

&lt;p&gt;You can probably see how we go about solving this then: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;we take all the keys found in data object we're updating,&lt;/li&gt;
&lt;li&gt;map them to properties we want to update, &lt;/li&gt;
&lt;li&gt;create a colon-prepended key for them, then &lt;/li&gt;
&lt;li&gt;add those values to the &lt;code&gt;ExpressionAttributeValues&lt;/code&gt; list. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The final result looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Uncharted&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;developer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Naughty Dog&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;publisher&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Sony&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;TableName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DYNAMODB_TABLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UpdateExpression&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SET latestUpdate = :updateTime&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ExpressionAttributeValues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;k&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UpdateExpression&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;`, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; = :&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
    &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ExpressionAttributeValues&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;`:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ExpressionAttributeValues&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;:updateTime&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;dynamodb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll notice a few things about the above code:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;we start our &lt;code&gt;UpdateExpression&lt;/code&gt; with &lt;code&gt;SET latestUpdate = :updateTime&lt;/code&gt;; the purpose of that is so we don’t need to deal with the edge case of the first item in our iteration through the keys. With that starting off our expression, we can simply concatenate the string with all the keys, starting with a colon to separate each value. Makes life easier, plus it's good practice to save that information. Two birds, one stone.&lt;/li&gt;
&lt;li&gt;We have to set the initial value of &lt;code&gt;ExpressionAttributeValues&lt;/code&gt; to an empty object &lt;code&gt;{}&lt;/code&gt;, so we can write the keys and values to it.&lt;/li&gt;
&lt;li&gt;In our &lt;code&gt;for&lt;/code&gt; loop, there’s an &lt;code&gt;if&lt;/code&gt; statement because we want to get every attribute &lt;em&gt;except&lt;/em&gt; &lt;code&gt;title&lt;/code&gt;, which is the &lt;code&gt;Key&lt;/code&gt; to our table. Even if it hasn’t changed, we can’t put that in the &lt;code&gt;UpdateExpression&lt;/code&gt; or DynamoDB will error. You're not allowed to put the &lt;code&gt;Key&lt;/code&gt; in the &lt;code&gt;UpdateExpression&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now we should see no errors when we send two separate requests to the same endpoint, the first which will create the game, the second which will update it with a new attribute. &lt;/p&gt;

&lt;h3&gt;
  
  
  Personal Takeaway
&lt;/h3&gt;

&lt;p&gt;I’m new to DynamoDB so I’m not sure if it’s crazy or clever that this was the way to achieve this type of behavior in the &lt;code&gt;update&lt;/code&gt; function. I have my complaints about the default implementation of the &lt;code&gt;update&lt;/code&gt; function, but at the same time it wasn't a huge leap of imagination to get the desired behavior, so perhaps in a sense this &lt;em&gt;is&lt;/em&gt; as flexible as marketed. &lt;/p&gt;

&lt;p&gt;In only a few days of playing with it, I'm starting to see the patterns one can utilize to fill in the gaps where desired built-ins might be missing. Let me know if this was helpful for you or if you've faced any similar blockers with DynamoDB!&lt;/p&gt;

</description>
      <category>aws</category>
      <category>dynamodb</category>
      <category>nosql</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Connecting AWS Lambda To A Postgres DB: Part 2</title>
      <dc:creator>Dan</dc:creator>
      <pubDate>Wed, 07 Oct 2020 07:37:17 +0000</pubDate>
      <link>https://dev.to/dengel29/connecting-aws-lambda-to-a-postgres-db-part-2-1n3h</link>
      <guid>https://dev.to/dengel29/connecting-aws-lambda-to-a-postgres-db-part-2-1n3h</guid>
      <description>&lt;h5&gt;
  
  
  In the &lt;a href="https://dev.to/dengel29/connecting-aws-lambda-to-a-postgres-db-part-1-3pfc"&gt;previous post&lt;/a&gt;, we got our Serverless function running locally, but hadn't set up our production database. This post deals with setting up an AWS RDS instance, configuring the security group to allow access, configuring the serverless.yaml file to hold different values for dev and prod environments, and setting up a Postgres Lambda Layer. It's a lot to cover, so let's get cracking!
&lt;/h5&gt;

&lt;h2&gt;
  
  
  Setting up AWS resources
&lt;/h2&gt;

&lt;p&gt;Because this is going to be an AWS Lambda, we’re going to set up some AWS resources. Although we’re only going to manually set up an AWS RDS instance – aka our production database – this section will also touch upon,  VPCs, subnets, and security groups. &lt;/p&gt;

&lt;h3&gt;
  
  
  Create an AWS RDS instance
&lt;/h3&gt;

&lt;p&gt;Here I’m going to defer to Amazon’s instructions on &lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_GettingStarted.CreatingConnecting.PostgreSQL.html" rel="noopener noreferrer"&gt;how to purchase and set up an RDS instance&lt;/a&gt;. Follow their instructions up to the point where they begin discussing security groups. Very important: when creating the database, do not forget open the “Additional Configuration” section and enter a database name! If you don’t give it a name the database will not be created.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmvrhhq3cujhnm8aa0m56.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmvrhhq3cujhnm8aa0m56.png" alt="Additional configuration page for rds setup"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also important: when you create a password for the database, do not forget it! Write it down somewhere. All the other information we’ll need soon can be read straight from the console if we ever forget it, but the database password is not so easily retrievable. &lt;/p&gt;

&lt;h3&gt;
  
  
  Configuring security group rules
&lt;/h3&gt;

&lt;p&gt;If you don’t do anything to the Security Group rules in the AWS Console, you’ll end up with a Connection Timeout every time you try to connect to your database.&lt;/p&gt;

&lt;p&gt;In order to change the Security Group rules, simply click the link under VPC security groups, which will take you to the page where you can configure it. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0keg0819fo6z2yj218ug.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0keg0819fo6z2yj218ug.png" alt="The settings page showing Connectivity &amp;amp; Security of an RDS instance"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From that page, scroll down to find the ‘Edit Inbound Rules’ section and change the rules to look like the ones in the screenshot below: &lt;br&gt;
Two rules with &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Type: PostgreSQL&lt;/li&gt;
&lt;li&gt;Protocol: TCP&lt;/li&gt;
&lt;li&gt;Port range: 5432&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One of those rules with source 0.0.0.0/0 and the other with ::/0. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsua8068pqob6f2cl9w9z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsua8068pqob6f2cl9w9z.png" alt="The settings for a security group to be able to access a Postgres instance"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Save the rules and go back to your RDS. Keep the window with our RDS instance open because we’re going to use some of the info shortly.&lt;/p&gt;
&lt;h2&gt;
  
  
  Configuring our production settings in our application
&lt;/h2&gt;

&lt;p&gt;So we have two main places that read information about our database: &lt;code&gt;config/config.json&lt;/code&gt;, which &lt;code&gt;sequelize-cli&lt;/code&gt; references for where to make migrations, and &lt;code&gt;connection.js&lt;/code&gt; which our application uses to make connections to the database. We’re going to need to make sure the information in these places is now up to date with our newly created production db credentials.&lt;/p&gt;
&lt;h3&gt;
  
  
  Update config.json
&lt;/h3&gt;

&lt;p&gt;Go into &lt;code&gt;config/config.json&lt;/code&gt; and under &lt;code&gt;production&lt;/code&gt; add the dbname, username, password, and host (the endpoint url) for our production database. Because this now has some sensitive information, it would be smart to add this file to our &lt;code&gt;.gitignore&lt;/code&gt;, so go ahead and do that.&lt;/p&gt;
&lt;h3&gt;
  
  
  Update connection.js with environment variables
&lt;/h3&gt;

&lt;p&gt;Next, we want to change the information we hardcoded into &lt;code&gt;connection.js&lt;/code&gt;. Instead of just replacing it with the production database information, we’re going to configure our serverless function to be able to mock different environments depending on what we want to test.&lt;/p&gt;

&lt;p&gt;So before we edit &lt;code&gt;connection.js&lt;/code&gt;, first head over to &lt;code&gt;serverless.yml&lt;/code&gt; and add the following, replacing the values with the values from &lt;em&gt;your&lt;/em&gt; production and development databases:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;custom&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;prod&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
      &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;
      &lt;span class="na"&gt;db_dialect&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;postgres"&lt;/span&gt;
      &lt;span class="na"&gt;db_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sls-starter-production&lt;/span&gt;
      &lt;span class="na"&gt;db_username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&lt;/span&gt;
      &lt;span class="na"&gt;db_password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;123456"&lt;/span&gt;
      &lt;span class="na"&gt;db_host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rds-endpoint.c2j1xg2t94lm.us-east-1.rds.amazonaws.com&lt;/span&gt;
      &lt;span class="na"&gt;db_port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5432"&lt;/span&gt;
    &lt;span class="na"&gt;dev&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
      &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;development&lt;/span&gt;
      &lt;span class="na"&gt;db_dialect&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;postgres"&lt;/span&gt;
      &lt;span class="na"&gt;db_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sls-starter&lt;/span&gt;
      &lt;span class="na"&gt;db_username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dengel&lt;/span&gt;
      &lt;span class="na"&gt;db_password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
      &lt;span class="na"&gt;db_host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;127.0.0.1&lt;/span&gt;
      &lt;span class="na"&gt;db_port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5432"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is going to allow us to run serverless offline without having to alter code based on which environment we need. In the &lt;code&gt;yaml&lt;/code&gt; above, &lt;code&gt;custom&lt;/code&gt; is part of the configuration that’s reserved for items we want to add that aren’t necessarily included in the options provided by Serverless Framework. Under that we’ve nested &lt;code&gt;env&lt;/code&gt;, and under that the two environments we intend to use: &lt;code&gt;prod&lt;/code&gt; and &lt;code&gt;dev&lt;/code&gt;. We’ll see how these values are accessible now.&lt;/p&gt;

&lt;p&gt;Under the &lt;code&gt;provider&lt;/code&gt; section of the yaml, paste the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${opt:stage, 'dev'}&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;DB_DIALECT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${self:custom.env.${self:provider.stage}.db_dialect}&lt;/span&gt;
    &lt;span class="na"&gt;DB_NAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${self:custom.env.${self:provider.stage}.db_name}&lt;/span&gt;
    &lt;span class="na"&gt;DB_USERNAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${self:custom.env.${self:provider.stage}.db_username}&lt;/span&gt;
    &lt;span class="na"&gt;DB_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${self:custom.env.${self:provider.stage}.db_password}&lt;/span&gt;
    &lt;span class="na"&gt;DB_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${self:custom.env.${self:provider.stage}.db_host}&lt;/span&gt;
    &lt;span class="na"&gt;DB_PORT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${self:custom.env.${self:provider.stage}.db_port}&lt;/span&gt;
    &lt;span class="na"&gt;NODE_ENV&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${self:custom.env.${self:provider.stage}.stage}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let me break this down. &lt;/p&gt;

&lt;p&gt;Let’s look at the first key, &lt;code&gt;stage&lt;/code&gt;. The &lt;code&gt;opt:stage&lt;/code&gt; that it is trying to read is from a flag we can pass to Serverless when we invoke it from the Command Line, we’ll do something like &lt;code&gt;sls offline -s dev&lt;/code&gt;, which tells it to run in the development environment.  We also could pass &lt;code&gt;prod&lt;/code&gt;. The second part of the value here, after the comma, just tells Serverless that if no &lt;code&gt;-s&lt;/code&gt; flag is  provided when we invoke serverless, to &lt;em&gt;default&lt;/em&gt; to &lt;code&gt;dev&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;So now we know that &lt;code&gt;opt:&lt;/code&gt; captures values passed in when we invoke Serverless. &lt;/p&gt;

&lt;p&gt;The values under &lt;code&gt;environment&lt;/code&gt; will set values accessible through &lt;code&gt;process.env&lt;/code&gt;, so we’ll be able to access them in our code. Let’s take a look at why they’re formatted the way they are.&lt;/p&gt;

&lt;p&gt;They’re formatted like this &lt;code&gt;DB_DIALECT: ${self:custom.env.${self:provider.stage}.db_dialect}&lt;/code&gt;. &lt;code&gt;self:custom&lt;/code&gt; refers to the &lt;code&gt;custom&lt;/code&gt; key we defined above in our &lt;code&gt;serverless.yaml&lt;/code&gt;, and then we simply use dot-notation to access to values inside of that. Furthermore, we’re nesting &lt;code&gt;${self:provider.stage}&lt;/code&gt; to see if it should access the values under &lt;code&gt;custom.env.dev&lt;/code&gt; or &lt;code&gt;custom.env.prod&lt;/code&gt;.  Again, if no flag is passed when we invoke any serverless command from the Command Line, it will default to the values under &lt;code&gt;custom.env.dev&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Now that we have this dynamic environment setting, we can remove the hard-coded configuration in our &lt;code&gt;connection.js&lt;/code&gt; and replace it with something more standard:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Sequelize&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sequelize&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sequelize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Sequelize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DB_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DB_USERNAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DB_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;dialect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;postgres&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;dialectModule&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DB_HOST&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sequelize&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s test this to see if it’s working. Replace the &lt;code&gt;msg&lt;/code&gt; variable in our main function in &lt;code&gt;handler.js&lt;/code&gt; with &lt;code&gt;process.env.DB_HOST&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/*...*/&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// comment this part out&lt;/span&gt;
    &lt;span class="c1"&gt;// await db.authenticate();&lt;/span&gt;

      &lt;span class="c1"&gt;// add this&lt;/span&gt;
    &lt;span class="nx"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DB_HOST&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="cm"&gt;/*...*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then try running the function offline in dev mode&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sls offline &lt;span class="nt"&gt;-s&lt;/span&gt; dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you should see your local server address when you visit &lt;a href="http://localhost:3000/dev/test" rel="noopener noreferrer"&gt;http://localhost:3000/dev/test&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Then try it in prod mode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sls offline &lt;span class="nt"&gt;-s&lt;/span&gt; prod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Visit &lt;a href="http://localhost:3000/prod/test" rel="noopener noreferrer"&gt;http://localhost:3000/prod/test&lt;/a&gt; (don’t forget that when you test your endpoints it will add the stage before the endpoint), and you should see your production database host. &lt;/p&gt;

&lt;p&gt;If you’re still getting connection timeouts, make sure your credentials are correct and that the Security Group is set up to receive inbound traffic as described in the earlier step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring VPC details
&lt;/h2&gt;

&lt;p&gt;We have a few final things to configure before we deploy our Lambda. First, we want to tell the Lambda which security groups, subnets, and region to be associated with. These can be found on the page for the RDS database we set up. Simply grab any of the two subnets in the list and copy- paste their identifiers. Same with the security group. We’ll also add these values under the &lt;code&gt;provider&lt;/code&gt; section:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
 &lt;span class="na"&gt;vpc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
    &lt;span class="na"&gt;securityGroupIds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;sg-8888888&lt;/span&gt;
    &lt;span class="na"&gt;subnetIds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;subnet-222222&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;subnet-1111111&lt;/span&gt;
  &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;us-east-1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are necessary for when we finally deploy it, but you wouldn’t know it now because it looks like our function is working! That’s a little misleading! It’s one of the takeaways I’ve gotten from this process: you might have what looks like a perfectly working serverless function, but it will error in production. Anyways, don’t worry about that just yet, we’ll be able to mitigate most of the problems before deployment, so don’t be discouraged if one pops up. &lt;/p&gt;

&lt;p&gt;Moving on, we have one last thing to do, which is set up our Postgres Lambda Layer, which will allow our Lambda to speak to our production database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up a Lambda layer
&lt;/h2&gt;

&lt;p&gt;There’s a lot of different tutorials out there on how to create a Lambda layer. I’ve tried several and this was by far the quickest and simplest approach for me, so it comes with my recommendation. &lt;/p&gt;

&lt;p&gt;First, create a folder in the root of your project called &lt;code&gt;layer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you’ve ever worked with Postgres before, you will have installed the native binaries, specifically one called &lt;code&gt;libpq&lt;/code&gt;. To find out for sure, use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find / &lt;span class="nt"&gt;-name&lt;/span&gt; libpq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you’ve installed Postgres before, you should see some file paths returned from this command (if you can’t find it, you can download the file from the layer folder in &lt;a href="https://github.com/dengel29/sls-sequelize-pg-starter" rel="noopener noreferrer"&gt;this Github repo&lt;/a&gt; which also has all the configuration boilerplate you need to get this up and running). If you do see it, &lt;code&gt;cd&lt;/code&gt; into one of those and copy the &lt;code&gt;libpq&lt;/code&gt; file (it might be called &lt;code&gt;libpq.so&lt;/code&gt; or &lt;code&gt;libpq.so.5&lt;/code&gt;) into the &lt;code&gt;layer&lt;/code&gt; folder in your project that you just created.&lt;/p&gt;

&lt;p&gt;Your folder structure should now look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fur9x5aan6nghtlrr7mcs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fur9x5aan6nghtlrr7mcs.png" alt="The final file structure should look like this"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next you’ll add some more configuration to your &lt;code&gt;serverless.yml&lt;/code&gt;  which will instruct Serverless to upload the layer to AWS, and have your Lambda utilize the layer. By doing this little configuration, Serverless takes care of most of the AWS configuration for  you. &lt;/p&gt;

&lt;p&gt;So let’s add two new details to the &lt;code&gt;serverless.yml&lt;/code&gt; (full final config can be found a little lower, if you're not certain about any details):&lt;/p&gt;

&lt;p&gt;1) At the top level of the &lt;code&gt;yaml&lt;/code&gt;,  add the following. Note that &lt;code&gt;path: layer&lt;/code&gt; refers to the folder our Postgres binary is located. We’ve named it &lt;code&gt;pg&lt;/code&gt; here but we could name it anything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;layers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pg&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;layer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2) In the section of the yml that describes the app, under function add :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;functions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;handler.index&lt;/span&gt;
    &lt;span class="na"&gt;events&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ANY /&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ANY&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{proxy+}'&lt;/span&gt;
    &lt;span class="na"&gt;layers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;Ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;PgLambdaLayer&lt;/span&gt;&lt;span class="pi"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We describe that the function in &lt;code&gt;app&lt;/code&gt; make use of the layer which gets named &lt;code&gt;PgLambdaLayer&lt;/code&gt;, based on what we called our layer in the previous step. If we named it &lt;code&gt;postgres&lt;/code&gt; instead of &lt;code&gt;pg&lt;/code&gt; we would have to instead write &lt;code&gt;{Ref: PostgresLambdaLayer}&lt;/code&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  serverless.yml in its entirety
&lt;/h2&gt;

&lt;p&gt;Now that we’ve added all this configuration, let’s look at what our whole &lt;code&gt;serverless.yml&lt;/code&gt;  file should look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sls-new-project&lt;/span&gt;
&lt;span class="na"&gt;custom&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;prod&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
      &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;
      &lt;span class="na"&gt;db_dialect&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;postgres"&lt;/span&gt;
      &lt;span class="na"&gt;db_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sls-starter-production&lt;/span&gt;
      &lt;span class="na"&gt;db_username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&lt;/span&gt;
      &lt;span class="na"&gt;db_password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;123456"&lt;/span&gt;
      &lt;span class="na"&gt;db_host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rds-endpoint.c2j1xg2t94lm.us-east-1.rds.amazonaws.com&lt;/span&gt;
      &lt;span class="na"&gt;db_port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5432"&lt;/span&gt;
    &lt;span class="na"&gt;dev&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
      &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;development&lt;/span&gt;
      &lt;span class="na"&gt;db_dialect&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;postgres"&lt;/span&gt;
      &lt;span class="na"&gt;db_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sls-starter&lt;/span&gt;
      &lt;span class="na"&gt;db_username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dengel&lt;/span&gt;
      &lt;span class="na"&gt;db_password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
      &lt;span class="na"&gt;db_host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;127.0.0.1&lt;/span&gt;
      &lt;span class="na"&gt;db_port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5432"&lt;/span&gt;
&lt;span class="na"&gt;layers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pg&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;layer&lt;/span&gt;
&lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws&lt;/span&gt;
  &lt;span class="na"&gt;runtime&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nodejs12.x&lt;/span&gt;
  &lt;span class="na"&gt;vpc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
    &lt;span class="na"&gt;securityGroupIds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;sg-8888888&lt;/span&gt;
    &lt;span class="na"&gt;subnetIds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;subnet-88888899&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;subnet-22222222&lt;/span&gt;
  &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;us-east-1&lt;/span&gt;
  &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${opt:stage, 'dev'}&lt;/span&gt;
  &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;DB_DIALECT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${self:custom.env.${self:provider.stage}.db_dialect}&lt;/span&gt;
    &lt;span class="na"&gt;DB_NAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${self:custom.env.${self:provider.stage}.db_name}&lt;/span&gt;
    &lt;span class="na"&gt;DB_USERNAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${self:custom.env.${self:provider.stage}.db_username}&lt;/span&gt;
    &lt;span class="na"&gt;DB_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${self:custom.env.${self:provider.stage}.db_password}&lt;/span&gt;
    &lt;span class="na"&gt;DB_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${self:custom.env.${self:provider.stage}.db_host}&lt;/span&gt;
    &lt;span class="na"&gt;DB_PORT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${self:custom.env.${self:provider.stage}.db_port}&lt;/span&gt;
    &lt;span class="na"&gt;NODE_ENV&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${self:custom.env.${self:provider.stage}.stage}&lt;/span&gt;
&lt;span class="na"&gt;functions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;handler.index&lt;/span&gt;
    &lt;span class="na"&gt;events&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ANY /&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ANY&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{proxy+}'&lt;/span&gt;
    &lt;span class="na"&gt;layers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;Ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;PgLambdaLayer&lt;/span&gt;&lt;span class="pi"&gt;}&lt;/span&gt;
&lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;serverless-offline&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;serverless-sequelize-migrations&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Deploying
&lt;/h2&gt;

&lt;p&gt;Now we’re ready to deploy. Make sure to change your function code back to using &lt;code&gt;db.authenticate()&lt;/code&gt; as that will be the proof that we’ve made a successfully db connection and that our Serverless app is utilizing the layer we just created to talk in Postgres to our RDS instance.&lt;/p&gt;

&lt;p&gt;This first deployment will be slower than the rest because it will have to create the Lambda layer, but subsequent deploys will skip this step. When you’re ready, go ahead and deploy it with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sls deploy &lt;span class="nt"&gt;-s&lt;/span&gt; prod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Serverless will output in the terminal all the steps it’s taking to deploy your Lambda, including the step of building your lambda layer. When it’s done, visit the link it’s provided you or directly go to the endpoint you created in order to see it in action!&lt;/p&gt;

&lt;p&gt;And if you see that your connection is successful, congrats! If we’re still seeing errors, I recommend again to check to see if your connection credentials are correct and that the security group is configured as mentioned earlier, allowing Postgres TCP connections from 0.0.0.0/0 and ::/0. &lt;/p&gt;

&lt;p&gt;If it’s working, you can move onto the next step, which is creating some migrations and models locally, pushing those migrations  to your production server, which will be covered in the next (much shorter) post coming soon.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>postgres</category>
      <category>serverless</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Connecting AWS Lambda To A Postgres DB: Part 1</title>
      <dc:creator>Dan</dc:creator>
      <pubDate>Wed, 07 Oct 2020 07:35:20 +0000</pubDate>
      <link>https://dev.to/dengel29/connecting-aws-lambda-to-a-postgres-db-part-1-3pfc</link>
      <guid>https://dev.to/dengel29/connecting-aws-lambda-to-a-postgres-db-part-1-3pfc</guid>
      <description>&lt;h1&gt;
  
  
  Part 0: Pre-requesites
&lt;/h1&gt;

&lt;p&gt;Serverless functions are, at their core, extremely simple. Configuration ends up being the biggest bugger. Still, there are a few things I assume in this tutorial:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Familiarity with Javascript, Node, npm. All installed&lt;/li&gt;
&lt;li&gt;An AWS account. &lt;a href="//console.aws.amazon.com/"&gt;Sign up for one&lt;/a&gt; if you don't have it.&lt;/li&gt;
&lt;li&gt;Serverless Framework configured. Serverless Framework's benefit is it creates and deploys a lot of AWS resources on your behalf. To do, though, that it needs be able to access those resources, so there is some initial configuration that needs to take place. For that, instead of re-write their docs &lt;a href="https://www.serverless.com/framework/docs/providers/aws/guide/credentials/" rel="noopener noreferrer"&gt;I'll point you to the Serverless blog&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Part 1: Setting up a Project with Serverless Framework
&lt;/h1&gt;




&lt;h3&gt;
  
  
  Scaffolding the Project
&lt;/h3&gt;

&lt;p&gt;To scaffold a Serverless project run in your Terminal: &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ serverless create —template aws-nodejs —path sls-new-project


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This will create a folder called &lt;code&gt;sls-new-project&lt;/code&gt; that contains just two files, &lt;code&gt;handler.js&lt;/code&gt; which has your function’s logic, and &lt;code&gt;serverless.yaml&lt;/code&gt; which contains all the configuration. Very minimal to start.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up a local database and Sequelize
&lt;/h3&gt;

&lt;p&gt;We want to use Postgres and an object-relational mapper (ORM) called Sequelize. So let's install those dependencies into our project via npm.&lt;/p&gt;

&lt;p&gt;First &lt;code&gt;npm init&lt;/code&gt; to create a &lt;code&gt;package.json&lt;/code&gt; in our project. Then start installing some dependencies: &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npm install --save pg
npm install --save pg-hstore
npm install --save sequelize
npm install -—save-dev sequelize-cli


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Because we’ll be running some migrations we want to use &lt;code&gt;sequelize-cli&lt;/code&gt; to generate those migrations. We can run &lt;code&gt;npx sequelize-cli init&lt;/code&gt; which will create a migrations folder, config which tells the cli how to connect to the database for each environment, models folder for our various models, and seeders. You can get the full instructions for initializing &lt;code&gt;sequelize-cli&lt;/code&gt; &lt;a href="https://sequelize.org/master/manual/migrations.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;If you read the contents of the just-created &lt;code&gt;config/config.json&lt;/code&gt; you’ll see it’s configured for MySQL. Few things to change: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go ahead and change those to &lt;code&gt;postgres&lt;/code&gt; and save them. &lt;/li&gt;
&lt;li&gt;Also, change the &lt;code&gt;username&lt;/code&gt; value under &lt;code&gt;development&lt;/code&gt; to the name of your root user of your device. &lt;/li&gt;
&lt;li&gt;Also, please change the name of the database to something like &lt;code&gt;sls-starter&lt;/code&gt; or something related to the name of your project.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Remember, this config &lt;em&gt;only&lt;/em&gt; tells the CLI how to access the database, so we also have to tell our application to access the database. We’ll do this in a separate file, in the next step.&lt;/p&gt;

&lt;p&gt;We don’t have any models yet, but we’ll start creating them soon. But last step before that we have to &lt;em&gt;create&lt;/em&gt; the local database: do so with the command &lt;code&gt;npx sequelize-cli db:create&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;If it fails, you probably missed changing something in the &lt;code&gt;config/config.json&lt;/code&gt; file. Follow the steps above to make sure the user is the root user on your device, the database name is unique, and you’re using the correct type of database &lt;code&gt;postgres&lt;/code&gt;. For now you only need to change those values under &lt;code&gt;development&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For reference, here’s my &lt;code&gt;config/config.json&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"development"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dengel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"database"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sls-starter"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dialect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"postgres"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dengel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"database"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"database_test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dialect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"postgres"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"production"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dengel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"database"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"database_production"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dialect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"postgres"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;When it succeeds you’ll see the message: &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

Sequelize CLI &lt;span class="o"&gt;[&lt;/span&gt;Node: 10.16.0, CLI: 6.2.0, ORM: 6.3.5]

Loaded configuration file &lt;span class="s2"&gt;"config/config.json"&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Using environment &lt;span class="s2"&gt;"development"&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Database sls-starter created.


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The link above can help with creating models too; for this tutorial we're going to leave that to the end, first simply ensuring we can make database connections successfully.&lt;/p&gt;

&lt;p&gt;At this point your project file structure should look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcl8d9f1cnue4qfxmkmx9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcl8d9f1cnue4qfxmkmx9.png" alt="aws-pg-file-structure-1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Connecting to the local database in the application
&lt;/h3&gt;

&lt;p&gt;Okay, we’ve installed a lot of things and now it’s time to write some connection logic. &lt;/p&gt;

&lt;p&gt;We'll do that in a separate file called &lt;code&gt;connection.js&lt;/code&gt;, which we'll create at the root of the project. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Sequelize&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sequelize&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sequelize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Sequelize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sls-starter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dengel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;dialect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;postgres&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;dialectModule&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;127.0.0.1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sequelize&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You’ll notice a few things about the above code:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;that we’ve hardcoded the &lt;code&gt;dbname&lt;/code&gt;, &lt;code&gt;username&lt;/code&gt;,  &lt;code&gt;password&lt;/code&gt; (which is null) and &lt;code&gt;db.endpoint.url&lt;/code&gt; in the configuration. This isn’t good practice and we will look at how to improve this and use environment variables to make this dynamic based on the environment in the next post.&lt;/li&gt;
&lt;li&gt;We require the &lt;code&gt;pg&lt;/code&gt; postgres &lt;code&gt;node_module&lt;/code&gt; here and pass that object in as the &lt;code&gt;dialectModule&lt;/code&gt; option in the &lt;code&gt;Sequelize&lt;/code&gt; constructor. This is necessary for the Lambda function, Sequelize, and Postgres to work together harmoniously. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We’ve exported that connection logic, now let’s import it into our &lt;code&gt;handler.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Delete everything that the &lt;code&gt;serverless create&lt;/code&gt; command created earlier in this file and let’s start fresh.&lt;/p&gt;

&lt;p&gt;We’re going to be using http triggers for the functions, so we also want to install the following packages:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npm install —-save serverless-http
npm install --save express


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then require them in our &lt;code&gt;handler.js&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use strict&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./connection.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;serverless&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;serverless-http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And now we can add a function to test our database connection.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authenticate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Connection successful&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Unable to connect to the database:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Unable to connect to the database:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;serverless&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We’re almost ready to test our function. &lt;/p&gt;

&lt;p&gt;When it comes to testing things, one of the most important factors is finding ways to speed up the feedback loop. It would be a shame if the only way to test our functions was by deploying them and seeing if they work on production. That’s why we’re going to install some more plug-ins.&lt;/p&gt;

&lt;h3&gt;
  
  
  Speeding up our feedback loop
&lt;/h3&gt;

&lt;p&gt;The Serverless Framework plugins we use assist our development, &lt;code&gt;serverless-offline&lt;/code&gt; to test our functions locally to speed up the feedback loop (crucial) and &lt;code&gt;serverless-sequelize-migrations&lt;/code&gt; which takes our migrations and runs them on the production environment for us. We’ll use it a little later in our project. These aren’t npm packages, but plugins that we install via the &lt;code&gt;serverless&lt;/code&gt; CLI then refer to in our &lt;code&gt;serverless.yaml&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;So first, from your project root run in the terminal the following commands:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

serverless plugin &lt;span class="nb"&gt;install&lt;/span&gt; —name serverless-offline
serverless plugin &lt;span class="nb"&gt;install&lt;/span&gt; —name serverless-sequelize-migrations


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then go into your &lt;code&gt;serverless.yaml&lt;/code&gt; file which we haven't touched at all yet.&lt;/p&gt;

&lt;p&gt;You can take a look at all the different options that are commented out. I will only touch on the ones that are important for us now.&lt;/p&gt;

&lt;p&gt;You can leave the &lt;code&gt;server&lt;/code&gt; and &lt;code&gt;provider&lt;/code&gt; configurations, and now we’re going to add a &lt;code&gt;plugins&lt;/code&gt; section at the highest level of the &lt;code&gt;yaml&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;serverless-offline&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;serverless-sequelize-migrations&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We can also change the details of the &lt;code&gt;functions&lt;/code&gt; section to more accurately reflect what’s now in our &lt;code&gt;handler.js&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;functions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;handler.index&lt;/span&gt;
    &lt;span class="na"&gt;events&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ANY /&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ANY&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{proxy+}'&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This tells Serverless how to configure out AWS Lambda when we eventually deploy it, but also what options will be available to use locally, and how to access our function (via handler.index, where &lt;code&gt;handler&lt;/code&gt; refers to what we named the file, and &lt;code&gt;index&lt;/code&gt; refers to what we exported in &lt;code&gt;module.exports&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now it’s time to check if it’s working.&lt;/p&gt;

&lt;h3&gt;
  
  
  Local Smoke Test and Next Steps
&lt;/h3&gt;

&lt;p&gt;A smoke test just a simple test to see if things are working as expected. The logic of our only function runs Sequelize’s &lt;code&gt;db.authenticate()&lt;/code&gt; function and prints whether it successfully connects or not.&lt;/p&gt;

&lt;p&gt;To test, we’ll run &lt;code&gt;sls offline&lt;/code&gt; which now starts a local mock of our serverless function. We can visit &lt;a href="http://localhost:3000/dev/test" rel="noopener noreferrer"&gt;http://localhost:3000/dev/test&lt;/a&gt; to see if our function is successful. And if everything was followed correctly, you should see “Connection successful” or whatever your success message in the function was in the browser. &lt;/p&gt;

&lt;p&gt;But, if you were to run &lt;code&gt;sls deploy&lt;/code&gt; at this point and try this in production, it would fail because &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;we don’t have a production database and,&lt;/li&gt;
&lt;li&gt;AWS Lambda can’t speak Postgres without some more extra configuration. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That’s what we’ll do in the &lt;a href="https://dev.to/dengel29/connecting-aws-lambda-to-a-postgres-db-part-2-1n3h"&gt;next post&lt;/a&gt;, as well as separating our environments.&lt;/p&gt;

</description>
      <category>serverless</category>
      <category>lambda</category>
      <category>aws</category>
      <category>postgres</category>
    </item>
    <item>
      <title>Loading Local Files in Firefox and Chrome</title>
      <dc:creator>Dan</dc:creator>
      <pubDate>Thu, 21 May 2020 03:41:47 +0000</pubDate>
      <link>https://dev.to/dengel29/loading-local-files-in-firefox-and-chrome-m9f</link>
      <guid>https://dev.to/dengel29/loading-local-files-in-firefox-and-chrome-m9f</guid>
      <description>&lt;p&gt;One of the many cool things about working in the browser is you can just drag and drop a local HTML file into it and see your work. No local server running or anything, just files and a browser, like Adam and Eve. But due to browser security settings, developing this way can still trigger CORS-related errors when you load in local files, such as an mp4. &lt;/p&gt;

&lt;p&gt;Let's see how to eliminate pesky CORS errors while doing this most foundational style of local development!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;So, I just spent about 10 minutes trying to load in a local audio file, and I kept getting the following error in the browser console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The HTMLMediaElement passed to createMediaElementSource has 
a cross-origin resource, the node will output silence.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Chrome you may see something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MediaElementAudioSource outputs zeroes due to CORS access 
restrictions for file:///Users/dengel/code/experi/dengel.m4a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I tried a few things that did not work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;adding the &lt;code&gt;crossorigin="anonymous&lt;/code&gt; attribute to the &lt;code&gt;&amp;lt;audio&amp;gt;&lt;/code&gt; tag&lt;/li&gt;
&lt;li&gt;passing in the absolute filepath to the .mp4&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These attempts just ended up raising different errors. It turns out you need to look to the &lt;em&gt;browser settings&lt;/em&gt; to get past these errors.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fixing this in Firefox
&lt;/h2&gt;

&lt;p&gt;In Firefox, first you need to navigate to about:config in the Firefox browser, search for the privacy.file_unique_origin setting, and set it from &lt;code&gt;true&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt; by double-clicking it. Voila, super easy!&lt;/p&gt;

&lt;h2&gt;
  
  
  Fixing this in Chrome
&lt;/h2&gt;

&lt;p&gt;If you're working in Chrome it's a little more laborious and requires using the Terminal (I'm on a Mac, but judging from this StackOverflow post, &lt;a href="https://stackoverflow.com/questions/18586921/how-to-launch-html-using-chrome-at-allow-file-access-from-files-mode"&gt;for PowerShell users it's not much different&lt;/a&gt;):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the Chrome address bar, navigate to chrome://version&lt;/li&gt;
&lt;li&gt;On this page, find and copy the value of "Command Line". It will look like &lt;code&gt;/Applications/Google Chrome.app/Contents/MacOS/Google Chrome&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Open your Terminal and paste in the file path to the Chrome executable you just copied&lt;/li&gt;
&lt;li&gt;If it's not recognizing the path, the spaces in the file path might need to be escaped with a forward-slash like &lt;code&gt;Google\ Chrome.app&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Before you hit enter, two more things to add to this command&lt;/li&gt;
&lt;li&gt;Add the following flag to the end of your command: &lt;code&gt;--allow-file-access-from-files&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Finally, add the folder or file you want to open at the end, like &lt;code&gt;audio.html&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Your final command in Terminal will look something like this (assuming you're within your project folder):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;/Applications/Google&lt;span class="se"&gt;\ &lt;/span&gt;Chrome.app/Contents/MacOS/Google&lt;span class="se"&gt;\ &lt;/span&gt;Chrome  
&lt;span class="nt"&gt;--allow-file-access-from-files&lt;/span&gt; audio.html 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the command is successful, it should open up a Chrome window with your folder or file that you specified in the last step. &lt;/p&gt;

&lt;p&gt;One gotcha I encountered was I needed to close my already-open instance of Chrome for the &lt;code&gt;allow-file-access-from-files&lt;/code&gt; flag to register. &lt;/p&gt;

&lt;p&gt;After that, my audio file was loaded and I got on my merry way. Hope this saves you a few minutes of searching! &lt;/p&gt;

</description>
      <category>beginners</category>
      <category>firefox</category>
      <category>chrome</category>
      <category>cors</category>
    </item>
  </channel>
</rss>
