<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Andrew Griffiths]]></title><description><![CDATA[Independent technology consultant helping companies build and scale using serverless technology.]]></description><link>https://andrewgriffithsonline.com</link><generator>RSS for Node</generator><lastBuildDate>Thu, 16 Aug 2018 16:50:57 GMT</lastBuildDate><item><title><![CDATA[Build a Realtime Serverless GraphQL API with Websockets on AWS]]></title><description><![CDATA[With the release of AWS AppSync we finally have the ability to create realtime serverless apps on AWS. Previously you were forced to spin up…]]></description><link>https://andrewgriffithsonline.com/blog/serverless-websockets-on-aws</link><guid isPermaLink="false">https://andrewgriffithsonline.com/blog/serverless-websockets-on-aws</guid><pubDate>Sun, 15 Jul 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;With the release of AWS AppSync we finally have the ability to create realtime serverless apps on AWS. Previously you were forced to spin up EC2 instances in order to create websocket connections as they are not supported by AWS Lambda.&lt;/p&gt;
&lt;p&gt;In the tutorial you’ll learn how to build a simple GraphQL API using AWS AppSync. Then you’ll write a client app in vanilla javascript (no frameworks) that receives realtime updates via websockets. Let’s get started!&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;#setup&quot;&gt;Set Up&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#create-graphql-schema&quot;&gt;Create GraphQL Schema&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#create-mapping-templates&quot;&gt;Create Mapping Templates&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#deploy-api-with-serverless&quot;&gt;Deploy AppSync GratphQL API with Serverless Framework&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#create-graphql-queries&quot;&gt;Create GraphQL Queries For Client Application&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#download-api-config&quot;&gt;Download API Config from AWS Console&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#client-side-application-code&quot;&gt;Isomorphic Vanilla JavaScript Client Code For Subscribing to Realtime API Updates&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#nodejs-client-build-process&quot;&gt;Node.js Client Application Build Process&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#nodejs-client&quot;&gt;Node.js Client Application&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#browser-client-build-process&quot;&gt;Browser Client Build Process&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#browser-client&quot;&gt;Browser Client&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;1. &lt;a name=&quot;setup&quot;&gt;&lt;/a&gt;Setup&lt;/h2&gt;
&lt;p&gt;Go ahead and install the serverless framework cli which we will be using to deploy our AppSync GraphQL API and create a new directory for our project.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ npm install -g serverless
$ mkdir realtime-chat
$ cd realtime-chat&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;h2&gt;2. &lt;a name=&quot;create-graphql-schema&quot;&gt;&lt;/a&gt;Create GraphQL Schema&lt;/h2&gt;
&lt;p&gt;We will define a basic GraphQL schema for our chat application.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-graphql&quot;&gt;&lt;code&gt;schema &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Query
    &lt;span class=&quot;token attr-name&quot;&gt;mutation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Mutation
    &lt;span class=&quot;token attr-name&quot;&gt;subscription&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Subscription
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

type Subscription &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    inbox&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Page
    &lt;span class=&quot;token directive function&quot;&gt;@aws_subscribe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;mutations&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;message&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

type Mutation &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    message&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Page&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

type Message &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;sentAt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

type Query &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token attr-name&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; String
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;A standard GraphQL schema apart from the realtime subscription which uses a special syntax to indicate to AWS AppSync which mutation to subscribe to (&lt;code&gt;@aws_subscribe(mutations: [&quot;message&quot;])&lt;/code&gt;), in this case the &lt;code&gt;message&lt;/code&gt; mutation.&lt;/p&gt;
&lt;h2&gt;3. &lt;a name=&quot;create-mapping-templates&quot;&gt;&lt;/a&gt;Create Mapping Templates&lt;/h2&gt;
&lt;p&gt;Now we have our schema defined we need to add resolvers for it. If you’re expecting to need to write a lambda function you’d be wrong! AppSync introduces the concept of &lt;a href=&quot;https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-reference-overview.html&quot;&gt;mapping templates&lt;/a&gt; which translate the client request to one the backing store (DynamoDB, elasticsearch etc) understands and then translates the response back to the client again.&lt;/p&gt;
&lt;p&gt;To keep things simple we are creating an API without a database. AppSync offers a special type of resolver called a &lt;a href=&quot;https://docs.aws.amazon.com/appsync/latest/devguide/tutorial-local-resolvers.html&quot;&gt;local resolver&lt;/a&gt; which does not persist the request data but instead just relays it on to whatever subscribers exist at the time.&lt;/p&gt;
&lt;p&gt;Let’s create a directory to house our mapping templates.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ mkdir mapping-templates&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Then let’s create the request template for our &lt;code&gt;message&lt;/code&gt; mutation in a file called &lt;code&gt;mapping-templates/Message.request.vtl&lt;/code&gt; which will extract the fields from the mutation request.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-vtl&quot;&gt;&lt;code&gt;{
  &quot;version&quot;: &quot;2017-02-28&quot;,
  &quot;payload&quot;: {
    &quot;body&quot;: &quot;${context.arguments.body}&quot;,
    &quot;from&quot;: &quot;${context.identity.username}&quot;,
    &quot;to&quot;:  &quot;${context.arguments.to}&quot;,
    &quot;sentAt&quot;: &quot;$util.time.nowISO8601()&quot;
  }
}&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;For the response we just use the standard forwarding template. Create a file called &lt;code&gt;mapping-templates/ForwardResult.response.vtl&lt;/code&gt; with the following contents.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-vtl&quot;&gt;&lt;code&gt;$util.toJson($context.result)&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Your folder structure should now look like the following:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ tree mapping-templates
mapping-templates
├── ForwardResult.response.vtl
└── Message.request.vtl&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;h2&gt;4. &lt;a name=&quot;deploy-api-with-serverless&quot;&gt;&lt;/a&gt;Deploy AppSync GraphQL API with Serverless Framework&lt;/h2&gt;
&lt;p&gt;Now we need to create a config file for the serverless framework to provision our API. In order to do this we’re going to use the &lt;a href=&quot;https://github.com/sid88in/serverless-appsync-plugin&quot;&gt;Serverless-AppSync-Plugin&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Install it with &lt;code&gt;npm&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ npm install --dev serverless-appsync-plugin&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Then create a &lt;code&gt;serverless.yml&lt;/code&gt; file with the following contents.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;token punctuation&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; realtime&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;chat

&lt;span class=&quot;token key atrule&quot;&gt;frameworkVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&gt;=1.21.0 &amp;lt;2.0.0&quot;&lt;/span&gt;

&lt;span class=&quot;token key atrule&quot;&gt;plugins&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; serverless&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;appsync&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;plugin

&lt;span class=&quot;token key atrule&quot;&gt;provider&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; aws
  &lt;span class=&quot;token key atrule&quot;&gt;region&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; eu&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;west&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;

&lt;span class=&quot;token key atrule&quot;&gt;custom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;awsAccountId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; $&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;AWS_ACCOUNT_ID&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;appSync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; realtimeChat
    &lt;span class=&quot;token key atrule&quot;&gt;apiKey&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; $&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;APPSYNC_API_KEY&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;apiId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; $&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;APPSYNC_API_ID&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;authenticationType&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; API_KEY
    &lt;span class=&quot;token key atrule&quot;&gt;schema&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; schema/schema.graphql
    &lt;span class=&quot;token key atrule&quot;&gt;serviceRole&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &quot;AppSyncServiceRole&quot; &lt;span class=&quot;token comment&quot;&gt;# AppSyncServiceRole is a role defined by amazon and available in all accounts&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;mappingTemplatesLocation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; mapping&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;templates
    &lt;span class=&quot;token key atrule&quot;&gt;mappingTemplates&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;dataSource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Chat
        &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Mutation
        &lt;span class=&quot;token key atrule&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; message
        &lt;span class=&quot;token key atrule&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Message.request.vtl
        &lt;span class=&quot;token key atrule&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ForwardResult.response.vtl
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;dataSource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Chat
        &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Subscription
        &lt;span class=&quot;token key atrule&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; inbox
        &lt;span class=&quot;token key atrule&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Message.request.vtl
        &lt;span class=&quot;token key atrule&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ForwardResult.response.vtl
    &lt;span class=&quot;token key atrule&quot;&gt;dataSources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; NONE  &lt;span class=&quot;token comment&quot;&gt;# use an AppSync local resolver&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Chat
        &lt;span class=&quot;token key atrule&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Chat relay&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;As you can see we set the data source type to &lt;code&gt;NONE&lt;/code&gt; in order to use the &lt;a href=&quot;https://docs.aws.amazon.com/appsync/latest/devguide/tutorial-local-resolvers.html&quot;&gt;local resolver&lt;/a&gt; as we do not want to persist the chat messages in a database but instead just forward them to other clients listening for updates.&lt;/p&gt;
&lt;p&gt;Our &lt;code&gt;serverless.yml&lt;/code&gt; config contains a few environment variables that we must supply. Let’s create a &lt;code&gt;.env&lt;/code&gt; file that contains our AWS Account ID and dynamically populates the other variables.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;# .env

export AWS_ACCOUNT_ID=123456789

export APPSYNC_API_ID=$(aws appsync list-graphql-apis \
  --query &apos;graphqlApis[?name==`realtimeChat`].apiId&apos; \
   --output text &gt;/dev/null 2&gt;&amp;1)

export APPSYNC_API_KEY=$(aws appsync list-api-keys \
  --api-id &quot;$APPSYNC_API_ID&quot; \
  --query &apos;apiKeys[0].id&apos; \
   --output text &gt;/dev/null 2&gt;&amp;1)&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Now we’re ready to deploy our API with a single command:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ .env &amp;&amp; sls deploy&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Congratulations! You’ve just deployed a GraphQL API with realtime support.&lt;/p&gt;
&lt;h2&gt;5. &lt;a name=&quot;create-graphql-queries&quot;&gt;&lt;/a&gt;Create GraphQL Queries For Client Application&lt;/h2&gt;
&lt;p&gt;The next thing we need to do is to create the GraphQL queries that we will be using from our client to query our API.&lt;/p&gt;
&lt;p&gt;First let’s create a directory to house our client code.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ mkdir src&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Then let’s create a directory for our queries.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ mkdir src/graphql&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Create a file at &lt;code&gt;src/graphql/inboxSubscription.js&lt;/code&gt; for our subscription query with the following contents:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; gql &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;graphql-tag&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; gql&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token string&quot;&gt;`
subscription Inbox($to: String) {
    inbox(to: $to) {
      from
      body
    }
}`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;This is just a simple subscription query which will return &lt;code&gt;from&lt;/code&gt; and &lt;code&gt;body&lt;/code&gt; message fields.&lt;/p&gt;
&lt;h2&gt;6. &lt;a name=&quot;download-api-config&quot;&gt;&lt;/a&gt;Download API Config from AWS Console&lt;/h2&gt;
&lt;p&gt;We need to download the config settings for the app so that it can connect to our GraphQL API.&lt;/p&gt;
&lt;p&gt;Navigate to AppSync section in the AWS Console. Select your API and download the web config settings.

  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 1264px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 73.1012658227848%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB60lEQVQ4y4WU247TMBCG85ILEuyuxCJ1AbVCQsANT8QFz4GExB17t7Q5OHFObc6HJml/Zrw1CyEplkZ2Lfvz/89MalzeLPFiscLLN++xWH3EYvkBy3efcL14iyfXr3FxeUvzK1xc3eIpzbx+frPCM7o3FUZd10iSBH3fg0ffDyirClJKOI6A8CTyokCWZUgpdnS2aVvMDSPLcmR5rn4cj0ccDgcUZQnblfhpOXA9D0EYYrvboaR9hlckQp8fh5ETLIri3weGE1B4PizHRZKmqEgxw5qmoXWN/X4/CVNAPsA29NAKHQLemw5Mss0qpe/DozTEcYz2ZFlD/rI83tBAGUQEcwkm4QcBgiBUStku51Df+wc4fkkDhXCw2ayxXq/h0Nq0LFgUPDtCoOu6aeCf/h+BFWwZwnQDRPFWKVP5HQ6neVDnpgpjaPJYoe8HSokthLLNxeH2iiiHXGmGzloeAzlPfIFt9RRD16IoSnDP9rTPPTup8BywqkpSlGJH/deUBVpqFX5A9eqpX6diFhhuE5i2B9sWVOVIWQ3DCGn68MXkeaHUct/qnBaUihHw4fUyT5F++4Lt188o8ozylykQX+CLc009q7Aki/79D2zuviOg4jCsPfP9/rco/OdQdwOqtlO504XgHHY8n4lfHNVsz/ods2MAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;AppSync Config Export Screen&quot;
        title=&quot;AppSync Config Export Screen&quot;
        src=&quot;/static/export_appsync_config-e94c457459089a523e603ec29753debd-c6c78.png&quot;
        srcset=&quot;/static/export_appsync_config-e94c457459089a523e603ec29753debd-b60d7.png 400w,
/static/export_appsync_config-e94c457459089a523e603ec29753debd-6aa63.png 800w,
/static/export_appsync_config-e94c457459089a523e603ec29753debd-c6c78.png 1264w&quot;
        sizes=&quot;(max-width: 1264px) 100vw, 1264px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;p&gt;You will have a file named &lt;code&gt;AppSync.js&lt;/code&gt; in your download area. Move this your &lt;code&gt;src&lt;/code&gt; directory and rename it to &lt;code&gt;config.js&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The config file you download should look like the following if you have left the default option for securing your API as &lt;code&gt;API_KEY&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&quot;graphqlEndpoint&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://xxxx.appsync-api.eu-west-1.amazonaws.com/graphql&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&quot;region&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;eu-west-1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&quot;authenticationType&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;API_KEY&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&quot;apiKey&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;xxxxxxxxxxxxxxxxxxxxxxxxx&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;h2&gt;7. &lt;a name=&quot;client-side-application-code&quot;&gt;&lt;/a&gt;Isomorphic Vanilla JavaScript Client Code For Subscribing to Realtime API Updates&lt;/h2&gt;
&lt;p&gt;We are going to create an isomorphic client - one that can be run either in the browser or via node.js in a terminal.&lt;/p&gt;
&lt;p&gt;First let’s install the dependencies we’ll need.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ npm install -s apollo-cache-inmemory apollo-client apollo-link aws-appsync aws-sdk es6-promise graphql graphql-cli graphql-tag isomorphic-fetch ws&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Then let’s create an entrypoint for the application.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-none&quot;&gt;&lt;code&gt;$ touch src/index.js&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Your app source code directory should now have the following contents.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-none&quot;&gt;&lt;code&gt;$ tree src
src
├── config.js
├── graphql
│   └── inboxSubscription.js
└── index.js&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Paste the following code into your &lt;code&gt;index.js&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; RECIPIENT &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Bobby&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;global&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;WebSocket&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  global&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;WebSocket &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;ws&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;global&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  global&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;window &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    setTimeout&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; setTimeout&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    clearTimeout&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; clearTimeout&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    WebSocket&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; global&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;WebSocket&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    ArrayBuffer&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; global&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ArrayBuffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    addEventListener&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    navigator&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; onLine&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;global&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;localStorage&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  global&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;localStorage &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    store&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    getItem&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;store&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    setItem&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;store&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    removeItem&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;store&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;es6-promise&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;polyfill&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;isomorphic-fetch&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Require config file downloaded from AWS console with endpoint and auth info&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; AppSyncConfig &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;./config&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; AWSAppSyncClient &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;aws-appsync&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; InboxSubscription &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./graphql/inboxSubscription&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Set up Apollo client&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; client &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AWSAppSyncClient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  url&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; AppSyncConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;graphqlEndpoint&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  region&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; AppSyncConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;region&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  auth&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    type&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; AppSyncConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;authenticationType&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    apiKey&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; AppSyncConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;apiKey&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

client&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hydrated&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;client&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; observable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; client&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;subscribe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; query&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; InboxSubscription&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; variables&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; to&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; RECIPIENT &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;realtimeResults&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;realtimeResults&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;realtime data: &apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  observable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;subscribe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    next&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; realtimeResults&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    complete&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;log&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    error&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;log&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;For this simple demo we have hardcoded the recipient to &lt;code&gt;Bobby&lt;/code&gt; but obviously you’d want to make this dynamic for a real application.&lt;/p&gt;
&lt;h2&gt;8. &lt;a name=&quot;nodejs-client-build-process&quot;&gt;&lt;/a&gt;Node.js Client Application Build Process&lt;/h2&gt;
&lt;p&gt;At this point we have all the source code written for our websockets client, we just need to implement the build process. Because the source code uses es6 features we need to transpile it using babel.&lt;/p&gt;
&lt;p&gt;Install the dev dependencies we’ll need.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ npm install --save-dev babel-cli babel-preset-es2015 rimraf webpack webpack-cli webpack-dev-server&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Now let’s build our application.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ rimraf build/ &amp;&amp; babel ./src --out-dir build/ --ignore ./node_modules,./.babelrc,./package.json,./npm-debug.log --copy-file&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;h2&gt;9. &lt;a name=&quot;nodejs-client&quot;&gt;&lt;/a&gt;Node.js Client Application&lt;/h2&gt;
&lt;p&gt;Now let’s run our application in node.js.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ node build/index.js&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Navigate to the &lt;code&gt;queries&lt;/code&gt; page in your AppSync API in the AWS console and run the following graphQL mutation to trigger some udpates.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-graphql&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;mutation&lt;/span&gt; Message &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    message&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Bobby&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Yo node!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        body
        to
        from
        sentAt
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 803px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 55.79078455790785%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAABi0lEQVQoz41Sy1LcMBD0/39LLnDNOScuYckhlQNk2V3s2OuXJOtpudOSTVioUOCqdo9UUlf3jIqql3g8j2hHibId8FB1qHuuuw5t30NNE6RSGan+CMXhqcTvwxF100BOGoOcMqspichPibwS/H67w7ebHe5+7VFWFY6n04ryD+pBbMIf4zlJoa2D+vkV4+0VBDeElBBCkHlIGxhrM+zGz/UljDFQSmPSGoV1HubHNdzuC5YQEGNEXCIWIsYZ8zwjcN85B5fY+7X+B09Rh26QdMjIE60aM6MfLIbHGpYDCpoHdUAwHoEXlmWBFHR+7nN/NV1p8xpJdGKiImWPwWMcFepWYvF0ZT28mxFTHcgUtIz1dGw4QA6vF4zuYOjWuBdkweQwxXO83HQK//uSwxS14RPbU3S8ryAqPqlWrDivvDrkIDwPp15ZF/Jl/jLnehNMw+iZomwGSLZFHs6QFJWnNkM14+aQk0lNf+voklnlJ5EuWA7CZPiNX9ZZMB24FHiv1uzh20Fcwph1KH8BIZVSYKiYmXQAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;Query for realtime updates in node.js application&quot;
        title=&quot;Query for realtime updates in node.js&quot;
        src=&quot;/static/query_realtime_updates_nodejs-4e3a1fb3201a27694bf43311925fa1ba-4998b.png&quot;
        srcset=&quot;/static/query_realtime_updates_nodejs-4e3a1fb3201a27694bf43311925fa1ba-94386.png 400w,
/static/query_realtime_updates_nodejs-4e3a1fb3201a27694bf43311925fa1ba-6eb2c.png 800w,
/static/query_realtime_updates_nodejs-4e3a1fb3201a27694bf43311925fa1ba-4998b.png 803w&quot;
        sizes=&quot;(max-width: 803px) 100vw, 803px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;p&gt;You should see the message appear immediately in your terminal.

  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 720px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 63.61111111111112%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAAsTAAALEwEAmpwYAAABdklEQVQ4y62T204CMRCGt9N2i8CusoDIQR5NrxGMGlkgJiBvPs6hsA1R44UkX/6205n+0y7Zx8sDLg6PuP6scbff4u6obA8b5bjBzV519b7E5dsTPtcrYfG6kFhd11ivlYx++K+EymOYE6McW5NA5BjGNJ6y0vpQ8R2nFAldVi/klWoGDtBY0+ASPQGEicCFMlkzzlxp0Y0BbQXohsSAGNG8r2vQNbLGc9Eb0rsY57XbCMeIzPWaRMtj5hrUAUSHPlF2EpIYjSHErkgzW2plPgE6RhzI6QMtLkVsLMbkUUOyZmO7/Cjs0E0B/b2VVtN2T2NukeN+arW1UoHCSGfQUsdasKKNM0qaqCtO8jMr98IOz66reFBp5EoYjkmx6E4fhZL8XItA28gmfhzZ6Myfvr3zC/McMj1FHLSJK/glsUm+5OwQrBaQNgpy23Nou+QwxANaqq6wcvmpo28LQ7xMbpNbd32L+dDRP8dLcU93zMX4e02d/MQXtAYrBsw12pAAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;Realtime updates in node.js application&quot;
        title=&quot;Realtime updates in node.js&quot;
        src=&quot;/static/results_realtime_updates_nodejs-a2a03ab508f68df59b10beabada3d201-eaa1a.png&quot;
        srcset=&quot;/static/results_realtime_updates_nodejs-a2a03ab508f68df59b10beabada3d201-1a3a5.png 400w,
/static/results_realtime_updates_nodejs-a2a03ab508f68df59b10beabada3d201-eaa1a.png 720w&quot;
        sizes=&quot;(max-width: 720px) 100vw, 720px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;h2&gt;10. &lt;a name=&quot;browser-client-build-process&quot;&gt;&lt;/a&gt;Browser Client Application Build Process&lt;/h2&gt;
&lt;p&gt;Remember the code we’ve written is isomorphic. That means it’ll run just as well in the browser.&lt;/p&gt;
&lt;p&gt;First install the dev dependencies we’ll need.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ npm install --save-dev webpack webpack-cli webpack-dev-server&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;We’re going to use &lt;a href=&quot;https://webpack.js.org/&quot;&gt;webpack&lt;/a&gt; to run our build process so we need to create a config file for it. Create a file called &lt;code&gt;webpack.config.js&lt;/code&gt; at the route of the project with the following contents.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; path &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;path&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  entry&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./src/index.js&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  output&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    filename&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;bundle.js&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    path&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;__dirname&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;dist&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;As the webserver will be serving assets from the &lt;code&gt;dist&lt;/code&gt; directory we need to add an &lt;code&gt;index.html&lt;/code&gt; file that includes the &lt;code&gt;bundle.js&lt;/code&gt; file which webpack will generate. Create a file at &lt;code&gt;dist/index.html&lt;/code&gt; with the following contents.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-html&quot;&gt;&lt;code&gt;&lt;span class=&quot;token doctype&quot;&gt;&amp;lt;!DOCTYPE html&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;AWS Serverless Websockets Demo&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text/javascript&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;bundle.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script language-javascript&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;h2&gt;10. &lt;a name=&quot;browser-client&quot;&gt;&lt;/a&gt;Browser Client Application&lt;/h2&gt;
&lt;p&gt;Run the following command which will start &lt;a href=&quot;https://github.com/webpack/webpack-dev-server&quot;&gt;&lt;code&gt;webpack-dev-server&lt;/code&gt;&lt;/a&gt; serving assets from the &lt;code&gt;dist&lt;/code&gt; directory.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ webpack-dev-server --mode development --content-base dist/&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Then navigate to &lt;code&gt;http://localhost:8080&lt;/code&gt; in your browser and open the dev tools as we’ll be logging the data to the console.&lt;/p&gt;
&lt;p&gt;Navigate to the &lt;code&gt;queries&lt;/code&gt; page in your AppSync API in the AWS console and run another graphQL mutation to trigger an update.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-graphql&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;mutation&lt;/span&gt; Message &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    message&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token attr-name&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Bobby&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;hello browser!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        body
        to
        from
        sentAt
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 834px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 56.11510791366906%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAABf0lEQVQoz42S3U7DMAyF9/6XPAwvALcghARXY7DRlrH1L39O06Y92FmHKiYBlT7ZUpLjY7srbS2K2iRqbbA9NMjKFnWrcKwqyLl1DmaOf7Fqlcb6dYf15hVVXUM5grKnQ2PMv4XknsCCLe4fHnH39ILNrkBRFMiyPJEfuYAIzpd/49uhJY9ABu7mCvblFtRPcM4yBPIeXdclQgiJrmPm/Iznc20cHBEL8sPOGdDTNYb8GTFExDFiHMfEOU9iTN/3KSbhGRFUWtoWh2yTSOY24CNrQPsGvXLobI/eBkTjMWgP4svtvkJ5bGB9B2IhkjgjRaSjlczHcxJjxIE3HccJYEZmWjAMA1plsd5+oslL2KOCLTXIeXh27bmAo4WgtFWLszBg+U1z7FlQHrwVFertAWqzh874t8qZ9xKmqGfBuWVxmASm6YIkyC5kRo3mrfLcXWtPNAx35niGTlqWlcvAvx0tRJa5bDotMJza8+GS5FAEpfrpMS7Elg6XS/jJeYZfsfpSooVl+q4AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;Query for realtime updates in browser application&quot;
        title=&quot;Query for realtime updates in browser&quot;
        src=&quot;/static/query_realtime_updates_browser-0a82b0eb442ab68523a3b4c3f730c8ee-9e1dc.png&quot;
        srcset=&quot;/static/query_realtime_updates_browser-0a82b0eb442ab68523a3b4c3f730c8ee-03786.png 400w,
/static/query_realtime_updates_browser-0a82b0eb442ab68523a3b4c3f730c8ee-8c39c.png 800w,
/static/query_realtime_updates_browser-0a82b0eb442ab68523a3b4c3f730c8ee-9e1dc.png 834w&quot;
        sizes=&quot;(max-width: 834px) 100vw, 834px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;p&gt;You should see the updates being logged to your browser’s console.

  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 465px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 107.0967741935484%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAVCAYAAABG1c6oAAAACXBIWXMAAAsTAAALEwEAmpwYAAACMElEQVQ4y9VUyW7bQAzV//9Krz0UvfVSIGicFFZiVLJlbZZl7dtIshbrlZxYgZO6BQr40BJ4GM5CzvYeFevzR9w9fMAn9Qu+fb3D/cMCnudhtVpBVZd4fPwuEYYhgiCQre/70PU17hcLLFUV6tMz4UlCsXQNjmtAMzfQNA2macJ1Xdi2LRPv93ukaYqmaS5QI89zOI4j533/IDdhKH4QohYNojBCFMVyUtd1bI2tTBjQibquw/F4fAMeG4YBfd+/gXI6neTEOI4S3J9tmiZM5/lreJ9MJsQVk4nO+FtTLoNvAQU3tv8g4b//hjP7eyJqWwsieYXu2KKqKtR1Tf4RZVnKPhNaUFtVQvo8xrFt2776imVZJCEbYZLh2bCx1Lfw4wQ2jdu2g4xkZ0nfRpplUm7ss/S4PRwOUuObzYb8AAovcAmO52O9C3AoSIZ5SScVFFRIHUckPyHqX1Qy+6x9LhaWZULho0d0Ig5M4hiNeLl2QLsJavOiRCF6kiTJcjyD5HiJWbYM+csvHdIsL6b+MA4ItiFyL5dz0y14yIlSM0eVVOiTGAO9WRdF6OgWA32gpAlvRlfmAjKda8BvechW7itkXgHh7SC0H6i3Buq1jobeqt3t0NKnCMOQG8xFRXlfZXirOWEV1yhc+hDLRksfMxGNRkJfFPLEQ1lgJKq8xl678jzBbVO0yJ0MuZWgzHKUrkOJA5z+EKNcq4NsTNYmJ6Qt6qqRvGT68LvhyvPMYz8BgcJeiul70jYAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;Realtime updates in browser application&quot;
        title=&quot;Realtime updates in browser&quot;
        src=&quot;/static/results_realtime_updates_browser-08fc191936bfbf4252832f03a09909c0-e378d.png&quot;
        srcset=&quot;/static/results_realtime_updates_browser-08fc191936bfbf4252832f03a09909c0-02b30.png 400w,
/static/results_realtime_updates_browser-08fc191936bfbf4252832f03a09909c0-e378d.png 465w&quot;
        sizes=&quot;(max-width: 465px) 100vw, 465px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;h2&gt;12. &lt;a name=&quot;conclusion&quot;&gt;&lt;/a&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;We’ve set up a serverless GraphQL API with node.js and browser clients consuming realtime updates via websockets. Not bad for &amp;#x3C;30 minutes work!&lt;/p&gt;
&lt;p&gt;Although AppSync is promoted as a managed GraphQL API service, for me its best feature is the ability to serve realtime updates. Previously you would have had to run a server 24/7 to do this. Now you get all the cost savings of serverless and without any of the headaches of managing servers.&lt;/p&gt;
&lt;p&gt;Full source code for this &lt;a href=&quot;https://github.com/techjacker/appsync-realtime-vanillajs&quot;&gt;serverless websockets example&lt;/a&gt; available on github.&lt;/p&gt;
&lt;p&gt;If you’re interested in learning more about building realtime serverless applications then check out my upcoming training course &lt;a href=&quot;/training/full-stack-serverless-graphql-appsync&quot;&gt;Full Stack Serverless GraphQL Apps on AWS AppSync&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Build a GeoSearch GraphQL API using AWS AppSync & Elasticsearch]]></title><description><![CDATA[My guide to building a GeoSearch GraphQL API using AWS AppSync & Elasticsearch has just been published on the  Serverless Framework blog…]]></description><link>https://andrewgriffithsonline.com/blog/build-geosearch-graphql-api-aws-appsyncelasticsearch</link><guid isPermaLink="false">https://andrewgriffithsonline.com/blog/build-geosearch-graphql-api-aws-appsyncelasticsearch</guid><pubDate>Thu, 07 Jun 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;My guide to building a GeoSearch GraphQL API using AWS AppSync &amp;#x26; Elasticsearch has just been published on the &lt;a href=&quot;https://serverless.com/blog/build-geosearch-graphql-api-aws-appsync-elasticsearch/&quot;&gt;Serverless Framework blog&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the tutorial you’ll learn how to build a GraphQL location search service similar to AirBnB’s using a fully serverless stack on AWS. Check out the &lt;a href=&quot;https://serverless.com/blog/build-geosearch-graphql-api-aws-appsync-elasticsearch/&quot;&gt;full article&lt;/a&gt; over at the Serverless Framework blog.&lt;/p&gt;
&lt;p&gt;If you’re interested in learning more about AWS AppSync then find out more about the &lt;a href=&quot;/training/full-stack-serverless-graphql-appsync&quot;&gt;training course&lt;/a&gt; I offer.&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Why Startups Should Build on Serverless Platforms in 2018]]></title><description><![CDATA[When you go to startup communities like  r/startups  or  indie hackers  you often see non-technical founders asking for advice about which…]]></description><link>https://andrewgriffithsonline.com/blog/180425-startups-should-build-on-serverless</link><guid isPermaLink="false">https://andrewgriffithsonline.com/blog/180425-startups-should-build-on-serverless</guid><category><![CDATA[serverless]]></category><category><![CDATA[startup]]></category><category><![CDATA[mvp]]></category><pubDate>Wed, 25 Apr 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;When you go to startup communities like &lt;a href=&quot;https://www.reddit.com/r/startups/&quot;&gt;r/startups&lt;/a&gt; or &lt;a href=&quot;https://www.indiehackers.com/&quot;&gt;indie hackers&lt;/a&gt; you often see non-technical founders asking for advice about which tech they should use to build their app. Invariably these end up in flame wars about development languages and frameworks. For me, this is totally missing the point. Yes ensure you are using experienced, talented developers. But the language or frameworks they use matters far less than the cloud platform you build your foundations on. That platform should be serverless.&lt;/p&gt;
&lt;h3&gt;What is serverless?&lt;/h3&gt;
&lt;p&gt;Serverless&lt;sup id=&quot;fnref-1&quot;&gt;&lt;a href=&quot;#fn-1&quot; class=&quot;footnote-ref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; is the umbrella term for the new breed of cloud services which do not require management of servers by customers. Hence server-&lt;em&gt;less&lt;/em&gt;. It was first popularised by Amazon Web Services (AWS) in 2014 with the launch of their &lt;a href=&quot;https://aws.amazon.com/lambda/&quot;&gt;Lambda service&lt;/a&gt;. Since then AWS and other cloud providers have launched dozens more services, including &lt;a href=&quot;https://aws.amazon.com/dynamodb/&quot;&gt;databases&lt;/a&gt;, &lt;a href=&quot;https://aws.amazon.com/sns/&quot;&gt;notifications&lt;/a&gt; and &lt;a href=&quot;https://aws.amazon.com/serverless/&quot;&gt;many more&lt;/a&gt;. The ecosystem has become so mature that large companies are now migrating their stacks wholesale to it.&lt;/p&gt;
&lt;h3&gt;Why is it such a big deal?&lt;/h3&gt;
&lt;p&gt;Because provisioning (configuring and installing the correct software) and managing (ensuring they remain active and secure) servers has historically accounted for a large percentage of the overall time it takes to develop and maintain a web application. Apart from the cost savings it brings, serverless also reduces the time to market for new products and features.&lt;/p&gt;
&lt;h3&gt;Only pay for what you use&lt;/h3&gt;
&lt;p&gt;Traditionally you would need to have a server running 24/7 to keep your application live. With serverless you are only charged when your application actually receives a request. With this pricing model you can keep your costs down to a minimum whilst you build up your customer base.&lt;/p&gt;
&lt;h3&gt;Scaling&lt;/h3&gt;
&lt;p&gt;Being able to deal with large numbers of users has been one of the hardest aspects of developing apps. With serverless, the cloud providers take on this responsibility and are able to do so on a massive scale, AWS claim that serverless is good for your “first ten million customers”.&lt;/p&gt;
&lt;h3&gt;The end of the protoype?&lt;/h3&gt;
&lt;p&gt;Traditionally startups would build a rough and ready first version which would need to be rebuilt from scratch as soon as they gained any traction. With serverless you no longer need to throw away your prototype when it becomes popular. If built correctly, it should scale to millions of users.&lt;/p&gt;
&lt;h3&gt;Go quicker, use serverless&lt;/h3&gt;
&lt;p&gt;In 2018, serverless is a mature technology with companies fast adopting it. It has made building an MVP quicker and cheaper than ever before. If you are a founder the first thing you should be telling your developers is “build on top of serverless platforms”.&lt;/p&gt;
&lt;p&gt;If you enjoyed this article and want to read more like it then follow me on &lt;a href=&quot;https://twitter.com/agriffonline&quot;&gt;twitter&lt;/a&gt; or &lt;a href=&quot;https://medium.com/@andrewgriffiths&quot;&gt;medium&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;footnotes&quot;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;Confusingly there is also an &lt;a href=&quot;https://serverless.com/&quot;&gt;application framework&lt;/a&gt; named serverless. It is just one of many tools you can use to develop on serverless platforms.&lt;/p&gt;
&lt;a href=&quot;#fnref-1&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content:encoded></item><item><title><![CDATA[How to Migrate a Go API to Serverless (in Under 10 Mins)]]></title><description><![CDATA[I’m going to step you through the process converting an existing Go API to serverless and deploying it to to AWS Lambda & API Gateway with…]]></description><link>https://andrewgriffithsonline.com/blog/180412-migrate-go-api-to-serverless-under-10-mins</link><guid isPermaLink="false">https://andrewgriffithsonline.com/blog/180412-migrate-go-api-to-serverless-under-10-mins</guid><category><![CDATA[aws-lambda]]></category><category><![CDATA[aws-sam]]></category><category><![CDATA[go]]></category><category><![CDATA[migrate]]></category><pubDate>Tue, 17 Apr 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I’m going to step you through the process converting an existing Go API to serverless and deploying it to to AWS Lambda &amp;#x26; API Gateway with &lt;a href=&quot;https://aws.amazon.com/about-aws/whats-new/2016/11/introducing-the-aws-serverless-application-model/&quot;&gt;AWS Severless Application Model (SAM)&lt;/a&gt;. The whole process should take under 10 minutes. Let’s get started!&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;#setup&quot;&gt;Set Up&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#convert-application-code-serverless&quot;&gt;Convert Application Code to Serverless&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#run-locally&quot;&gt;Build and Run Locally&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#package&quot;&gt;Package Application for AWS Lambda&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#deploy&quot;&gt;Deploy with AWS SAM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#test-deployed-api&quot;&gt;Test Deployed Serverless API&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;1. &lt;a name=&quot;setup&quot;&gt;&lt;/a&gt;Setup&lt;/h2&gt;
&lt;p&gt;Our example API uses the &lt;a href=&quot;https://github.com/julienschmidt/httprouter&quot;&gt;&lt;code&gt;HttpRouter&lt;/code&gt; package&lt;/a&gt; so let’s install that first.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ go get github.com/julienschmidt/httprouter&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ tree
.
├── main.go
└── handlers.go&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;We have a single HTTP handler defined that will return a 200 HTTP response with the body &lt;code&gt;ok&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-go&quot;&gt;&lt;code&gt;# handlers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;go&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;package&lt;/span&gt; main

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;net/http&quot;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;HealthHandler&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;w http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ResponseWriter&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; r &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    w&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;WriteHeader&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;StatusOK&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    w&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;ok&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Our entrypoint to the application, the &lt;code&gt;main&lt;/code&gt; function, attaches the &lt;code&gt;HealthHandler&lt;/code&gt; to the &lt;code&gt;/healthz&lt;/code&gt; route and listens for HTTP requests on port &lt;code&gt;8080&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-go&quot;&gt;&lt;code&gt;# main&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;go&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;package&lt;/span&gt; main

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;fmt&quot;&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;log&quot;&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;net/http&quot;&lt;/span&gt;

    &lt;span class=&quot;token string&quot;&gt;&quot;github.com/julienschmidt/httprouter&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    serverPort &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8000&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    router &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; httprouter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;New&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Handler&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;GET&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/healthz&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;HandlerFunc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;goserverlessapi&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;HealthHandler&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    fmt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Server listening on port: %d\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; serverPort&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Fatal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ListenAndServe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fmt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Sprintf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;:%d&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; serverPort&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; router&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Let’s build and run this locally to check everything’s working okay.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ go build -o go-serverless-api &amp;&amp; ./go-serverless-api
Server listening on port: 8080&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;h2&gt;2. &lt;a name=&quot;convert-application-code-serverless&quot;&gt;&lt;/a&gt;Convert Application Code to Serverless&lt;/h2&gt;
&lt;p&gt;In order to deploy to a serverless backend we need to be able to handle requests from AWS Lambda. Lambda functions have a different signature to &lt;a href=&quot;https://golang.org/pkg/net/http/#Handler&quot;&gt;regular HTTP handlers&lt;/a&gt;. Imagine if we had not one but hundreds in our application. We would have to manually update all the functions and re-write tests and in doing so we would forfeit our ability to deploy to non-serverless backends.&lt;/p&gt;
&lt;p&gt;There is a solution which avoids all the problems just listed. We will create a modified entrypoint just for AWS Lambda. Using the &lt;a href=&quot;https://github.com/apex/gateway&quot;&gt;&lt;code&gt;gateway&lt;/code&gt; package&lt;/a&gt; we will swap out &lt;code&gt;net/http&lt;/code&gt;’s &lt;code&gt;ListenAndServe&lt;/code&gt; for &lt;code&gt;gateway.ListenAndServe&lt;/code&gt; which will convert the payload that AWS Lambda provides into the &lt;a href=&quot;https://godoc.org/net/http#Request&quot;&gt;&lt;code&gt;*http.Request&lt;/code&gt;&lt;/a&gt; type that HTTP handlers accept.&lt;/p&gt;
&lt;p&gt;In order to implement this second entrypoint we need to reorganise our project. We will create a directory for the AWS Lambda one and move our original entrypoint to a new folder too.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;# original entrypoint moved to new location
$ mkdir -p cmd/go-serverless-api

# new entrypoint for lambda
$ mkdir -p cmd/go-serverless-api-lambda&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;We will copy the &lt;code&gt;main.go&lt;/code&gt; file into each of these new directories and then remove it from the root of our project.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ cp main.go cmd/go-serverless-api
$ cp main.go cmd/go-serverless-api-lambda
$ rm main.go&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ tree
.
├── cmd
│   ├── go-serverless-api
│   │   └── main.go
│   └── go-serverless-api-lambda
│       └── main.go
└── handlers.go&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;The package in the root of our project is no longer going to be the &lt;code&gt;main&lt;/code&gt; package (the one Go uses to run your application). We will rename it to &lt;code&gt;goserverlessapi&lt;/code&gt; so that we can import it as a library into our new entrypoints which will both become &lt;code&gt;main&lt;/code&gt; packages.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ grep -l &apos;package main&apos; *.go | xargs sed -i &apos;s/package main/package goserverlessapi/g&apos;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;After a simple find and replace on the Go files in the root of your project your &lt;code&gt;handlers.go&lt;/code&gt; should look like this.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-go&quot;&gt;&lt;code&gt;# handlers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;go&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;package&lt;/span&gt; goserverlessapi
&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;net/http&quot;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;HealthHandler&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;w http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ResponseWriter&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; r &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    w&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;WriteHeader&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;StatusOK&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    w&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;ok&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Now we need to update our original entrypoint to import the &lt;code&gt;goserverlessapi&lt;/code&gt; package and access the &lt;code&gt;HealthHandler&lt;/code&gt; function as an export from that. Note that you will need to modify the import path of the &lt;code&gt;goserverlessapi&lt;/code&gt; package to match that of your project root’s location in your &lt;code&gt;$GOPATH&lt;/code&gt;. The correct path for the &lt;a href=&quot;https://github.com/techjacker/go-serverless-api&quot;&gt;example application on github&lt;/a&gt; used in this tutorial is &lt;code&gt;github.com/techjacker/go-serverless-api&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-go&quot;&gt;&lt;code&gt;# cmd&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;go&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;serverless&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;api&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;main&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;go&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;package&lt;/span&gt; main

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;fmt&quot;&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;log&quot;&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;net/http&quot;&lt;/span&gt;

    &lt;span class=&quot;token string&quot;&gt;&quot;github.com/julienschmidt/httprouter&quot;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;github.com/techjacker/go-serverless-api&quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    serverPort &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8080&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    router &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; httprouter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;New&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Handler&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;GET&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/healthz&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;HandlerFunc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;goserverlessapi&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;HealthHandler&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;
    fmt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Server listening on port: %d\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; serverPort&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Fatal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ListenAndServe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fmt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Sprintf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;:%d&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; serverPort&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; router&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Next update the AWS Lambda entrypoint. We are going to use the &lt;a href=&quot;https://github.com/apex/gateway&quot;&gt;&lt;code&gt;gateway&lt;/code&gt;&lt;/a&gt; package which is a drop-in replacement for Go net/http when running on AWS Lambda &amp;#x26; API Gateway.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ go get github.com/apex/gateway&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-go&quot;&gt;&lt;code&gt;# cmd&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;go&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;serverless&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;api&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;lambda&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;main&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;go&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;package&lt;/span&gt; main

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;log&quot;&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;net/http&quot;&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;github.com/apex/gateway&quot;&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;github.com/julienschmidt/httprouter&quot;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;github.com/techjacker/go-serverless-api&quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    router &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; httprouter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;New&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Handler&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;GET&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/healthz&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;HandlerFunc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;goserverlessapi&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;HealthHandler&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Fatal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;gateway&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ListenAndServe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; router&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;We have added &lt;code&gt;gateway&lt;/code&gt; to our imports and swapped it out for &lt;code&gt;http.ListenAndServe&lt;/code&gt;. The port value is redundant in the Lambda context and the &lt;code&gt;gateway&lt;/code&gt; package discards it so we can safely remove the port constant and replace it with an empty string. In addition we have included our &lt;code&gt;HealthHandler&lt;/code&gt; from the &lt;code&gt;go-serverless-api&lt;/code&gt; package (the package in the root our of project which used to be our main package) as our handler for the &lt;code&gt;/healthz&lt;/code&gt; path.&lt;/p&gt;
&lt;h2&gt;3. &lt;a name=&quot;run-locally&quot;&gt;&lt;/a&gt; Build and Run Locally&lt;/h2&gt;
&lt;p&gt;Let’s build and run our original HTTP API again.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ go build \
    -o go-serverless-api \
    ./cmd/go-serverless-api

$ ./go-serverless-api
Server listening on port: 8080&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Open another terminal window and query it.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ curl -s http://localhost:8080/healthz
ok&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Everything still works!&lt;/p&gt;
&lt;p&gt;Let’s do the same with the AWS Lambda version.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ go build \
    -o go-serverless-api-lambda \
    ./cmd/go-serverless-api-lambda

$ ./go-serverless-api-lambda&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Again, open a new terminal and query it.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ curl -s http://localhost:8080/healthz
http: error: ConnectionError: HTTPConnectionPool(host=&apos;localhost&apos;, port=8080): Max retries exceeded with url: /healthz (Caused by NewConnectionError(&apos;&lt;urllib3.connection.HTTPConnection object at 0x7f57f5b69a58&gt;: Failed to establish a new connection: [Errno 111] Connection refused&apos;,)) while doing GET request to URL: http://localhost:8080/healthz&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Don’t worry this error is expected as the AWS Lambda version is not listening for HTTP connections but instead expects to be fed an &lt;a href=&quot;https://godoc.org/github.com/aws/aws-lambda-go/events#APIGatewayProxyRequest&quot;&gt;&lt;code&gt;APIGatewayProxyRequest&lt;/code&gt;&lt;/a&gt; type.&lt;/p&gt;
&lt;h2&gt;4. &lt;a name=&quot;package&quot;&gt;&lt;/a&gt;Package Application For AWS Lambda&lt;/h2&gt;
&lt;p&gt;Build the binary for linux, the operating system that AWS Lambda uses.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ GOOS=linux go build \
    -o go-serverless-api-lambda \
    ./cmd/go-serverless-api-lambda&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;AWS Lambda requires that function code be bundled into a zip so let’s go ahead and compress the binary.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ zip go-serverless-api-lambda.zip go-serverless-api-lambda&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;We will be using the created &lt;code&gt;go-serverless-api-lambda.zip&lt;/code&gt; in the final step - deployment.&lt;/p&gt;
&lt;h2&gt;5. &lt;a name=&quot;deploy&quot;&gt;&lt;/a&gt;Deploy&lt;/h2&gt;
&lt;p&gt;I’ve seen some tutorials that use the &lt;a href=&quot;https://aws.amazon.com/cli/&quot;&gt;AWS CLI tools&lt;/a&gt; to deploy to AWS Lambda using ad hoc commands. This is absolutely the wrong approach to take! You should be automating your infrastructure just like every other aspect of your application. The industry standard for deployment is either &lt;a href=&quot;https://www.terraform.io/&quot;&gt;Terraform&lt;/a&gt; or &lt;a href=&quot;https://aws.amazon.com/cloudformation/&quot;&gt;AWS Cloudformation&lt;/a&gt;. Both give you a declarative way to build your infrastructure. You save this configuration in YAML/JSON (Cloudformation) or HCL (Terraform) files which you commit to your repository. The problem with doing things this way is that you have to deal with all of the low level details of the stack. It would be nice if we had a way of describing our infrastructure at a high level in under 20 lines of code instead of hundreds. Enter &lt;a href=&quot;https://aws.amazon.com/about-aws/whats-new/2016/11/introducing-the-aws-serverless-application-model/&quot;&gt;AWS Severless Application Model (SAM)&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;AWS Severless Application Model (SAM)&lt;/h4&gt;
&lt;p&gt;SAM is a new standard spearheaded by Amazon aimed at making deploying serverless infrastructure simpler and more concise. SAM is an open source specification - &lt;a href=&quot;https://github.com/awslabs/serverless-application-model/blob/develop/versions/2016-10-31.md&quot;&gt;see the full reference guide&lt;/a&gt;. Hopefully other cloud vendors will adopt this in the future and it will become possible to deploy seamlessly to multiple clouds with a single configuration.&lt;/p&gt;
&lt;h4&gt;Deploy with AWS SAM&lt;/h4&gt;
&lt;p&gt;Add the following YAML file to the root of your project. This is a SAM template that configures an AWS Lambda Function that runs your Go app and deploys it behind an HTTP interface provided by AWS API Gateway.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;token comment&quot;&gt;# template.yaml&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;AWSTemplateFormatVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;2010-09-09&apos;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;Transform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;AWS::Serverless-2016-10-31&apos;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;Description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Boilerplate Go API.&apos;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;Resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;GoAPI&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token key atrule&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; AWS&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;Serverless&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;Function
&lt;/span&gt;    &lt;span class=&quot;token key atrule&quot;&gt;Properties&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      &lt;span class=&quot;token key atrule&quot;&gt;Handler&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; go&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;serverless&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;api&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;lambda
&lt;/span&gt;      &lt;span class=&quot;token key atrule&quot;&gt;Runtime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; go1.x
      &lt;span class=&quot;token key atrule&quot;&gt;CodeUri&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ./go&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;serverless&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;api&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;lambda.zip
      &lt;span class=&quot;token key atrule&quot;&gt;Events&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;          &lt;span class=&quot;token key atrule&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Api
&lt;/span&gt;          &lt;span class=&quot;token key atrule&quot;&gt;Properties&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;            &lt;span class=&quot;token key atrule&quot;&gt;Method&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ANY
&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;            &lt;span class=&quot;token key atrule&quot;&gt;Path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; /&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;proxy+&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;The line &lt;code&gt;Type: AWS::Serverless::Function&lt;/code&gt; creates a Lambda function that is handled (&lt;code&gt;Handler: go-serverless-api-lambda&lt;/code&gt;) by the binary file we built earlier. This Lambda function can respond to any number of events triggered by other AWS services such as those triggered by AWS S3 and Kinesis. The documentation contains the &lt;a href=&quot;https://github.com/awslabs/serverless-application-model/blob/develop/versions/2016-10-31.md#event-source-types&quot;&gt;full list of event of sources&lt;/a&gt;. In our case we want it to respond to HTTP requests via API Gateway therefore we set the event to &lt;code&gt;Type: Api&lt;/code&gt;. SAM implicitly creates an API Gateway for us as part of this which we then configure to respond to any type of HTTP request by setting the method to &lt;code&gt;ANY&lt;/code&gt;). We tell our API to handle all paths below and including the root by adding &lt;code&gt;Path: /{proxy+}&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We still need to upload the zip containing our Go binary to AWS S3. Ensure you have an S3 bucket created ready to receive our zip. This is a one-time operation you’ll want to do manually.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ aws s3 mb s3://my-bucket&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;The following command will upload the zip and create a packaged SAM template.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ aws cloudformation package \
    --template-file template.yaml \
    --s3-bucket my-bucket \
    --output-template-file packaged-template.yaml&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;You should now have a &lt;code&gt;packaged-template.yaml&lt;/code&gt; file pointing to the uploaded zip.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;token comment&quot;&gt;# packaged-template.yaml&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;AWSTemplateFormatVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;2010-09-09&apos;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;Transform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;AWS::Serverless-2016-10-31&apos;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;Description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Boilerplate Go API.&apos;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;Resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;GoAPI&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; AWS&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;Serverless&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;Function
    &lt;span class=&quot;token key atrule&quot;&gt;Properties&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;Handler&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; go&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;serverless&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;api&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;lambda
      &lt;span class=&quot;token key atrule&quot;&gt;Runtime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; go1.x
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      &lt;span class=&quot;token key atrule&quot;&gt;CodeUri&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; s3&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;//my&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;bucket/8982639e71e0d433cd99f9fa4207ecbe
&lt;/span&gt;      &lt;span class=&quot;token key atrule&quot;&gt;Events&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Api
          &lt;span class=&quot;token key atrule&quot;&gt;Properties&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token key atrule&quot;&gt;Method&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ANY
            &lt;span class=&quot;token key atrule&quot;&gt;Path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; /&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;proxy+&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Now let’s deploy using this new packaged template.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ aws cloudformation deploy \
    --template-file packaged-template.yaml \
    --stack-name go-serverless-api-stack \
    --capabilities CAPABILITY_IAM&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;The &lt;code&gt;--capabilities CAPABILITY_IAM&lt;/code&gt; flag is required for cloudformation to create the stack for you as it will involve modifying IAM permissions - AWS mandate you set this explicitly as a safety measure. Under the hood the SAM template is compiled into a regular cloudformation template which is hundreds of lines longer. All of is completely hidden from the user (although you are free to inspect the compiled cloudformation template if you wish).&lt;/p&gt;
&lt;h2&gt;&lt;a name=&quot;test-deployed-api&quot;&gt;&lt;/a&gt;Setup 6. Test Deployed Serverless API&lt;/h2&gt;
&lt;p&gt;In order to discover the endpoint of our deployed API we need find out the API Gateway REST &lt;code&gt;id&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ aws apigateway get-rest-apis
{
    &quot;items&quot;: [
        {
            &quot;id&quot;: &quot;0qu18x8pyd&quot;,
            &quot;name&quot;: &quot;go-serverless-api-stack&quot;,
            &quot;createdDate&quot;: 1523987269,
            &quot;version&quot;: &quot;1.0&quot;,
            &quot;apiKeySource&quot;: &quot;HEADER&quot;,
            &quot;endpointConfiguration&quot;: {
                &quot;types&quot;: [
                    &quot;EDGE&quot;
                ]
            }
        }
    ]
}&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;AWS API Gateway addresses take the following format.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-txt&quot;&gt;&lt;code&gt;https://&amp;lt;api-rest-id&amp;gt;.execute-api.&amp;lt;your-aws-region&amp;gt;.amazonaws.com/&amp;lt;api-stage&amp;gt;&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;A &lt;a href=&quot;https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-stages.html&quot;&gt;stage&lt;/a&gt; is Amazon’s term for a deployment. SAM creates two different stages for you: &lt;code&gt;Stage&lt;/code&gt; and &lt;code&gt;Prod&lt;/code&gt;. Note the title case which is also used in the URLs! I think AWS forgot that everyone calls their test environment &lt;code&gt;Staging&lt;/code&gt; not &lt;code&gt;Stage&lt;/code&gt; but nevermind!&lt;/p&gt;
&lt;p&gt;So SAM has set up endpoints for us at the following locations.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-none&quot;&gt;&lt;code&gt;https://0qu18x8pyd.execute-api.eu-west-1.amazonaws.com/Stage
https://0qu18x8pyd.execute-api.eu-west-1.amazonaws.com/Prod&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Let’s invoke our API.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ curl -s https://0qu18x8pyd.execute-api.eu-west-1.amazonaws.com/Prod
{&quot;message&quot;:&quot;Missing Authentication Token&quot;}&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;No need to panic! This is the &lt;a href=&quot;https://docs.aws.amazon.com/apigateway/latest/developerguide/amazon-api-gateway-using-stage-variables.html&quot;&gt;standard API Gateway error&lt;/a&gt; when you make a request to the root resource without defining a handler for it. The only handler we have defined is &lt;code&gt;/healthz&lt;/code&gt;, so let’s try that.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ curl -s https://0qu18x8pyd.execute-api.eu-west-1.amazonaws.com/Prod/healthz
ok&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Voila! Our API is now being powered by a serverless backend.&lt;/p&gt;
&lt;p&gt;Full code for this tutorial available on &lt;a href=&quot;https://github.com/techjacker/go-serverless-api&quot;&gt;github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I’ll be posting more articles on Go and Serverless soon. Follow me on &lt;a href=&quot;https://twitter.com/agriffonline&quot;&gt;twitter&lt;/a&gt; or &lt;a href=&quot;https://medium.com/@andrewgriffiths&quot;&gt;medium&lt;/a&gt; to get notified when I do.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Deploy your Flask API to any Serverless Cloud Platform using this Simple Pattern]]></title><description><![CDATA[I’m going to demonstrate how to make a Flask app serverless without locking you into any tooling or cloud platforms. It doesn’t require any…]]></description><link>https://andrewgriffithsonline.com/blog/180412-deploy-flask-api-any-serverless-cloud-platform</link><guid isPermaLink="false">https://andrewgriffithsonline.com/blog/180412-deploy-flask-api-any-serverless-cloud-platform</guid><category><![CDATA[aws-lambda]]></category><category><![CDATA[aws-sam]]></category><category><![CDATA[flask]]></category><category><![CDATA[terraform]]></category><pubDate>Thu, 12 Apr 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I’m going to demonstrate how to make a Flask app serverless without locking you into any tooling or cloud platforms. It doesn’t require any application code changes or serverless frameworks so you can continue to develop locally like you always have.&lt;/p&gt;
&lt;p&gt;Ideally you should re-architect your application into small discrete functions to take full advantage of serverless. However, if you want to migrate a legacy application or just a quick way to get started with serverless then this is a good approach to take.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;#create-flask-app&quot;&gt;Create Flask Application&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#make-app-serverless&quot;&gt;Make the Application Serverless&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bundle-app&quot;&gt;Package the Application into Zip for Lambda&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#deploy-app&quot;&gt;Deploy with Terraform&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;1. &lt;a name=&quot;create-flask-app&quot;&gt;&lt;/a&gt;Create Flask Application&lt;/h2&gt;
&lt;p&gt;We are going to create a Flask application for Python3.6+.&lt;/p&gt;
&lt;h4&gt;Setup&lt;/h4&gt;
&lt;p&gt;First create a virtual environment and install dependencies.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ python3 -m venv env
$ source env/bin/activate
$ pip install flask flask-lambda-python36 http-prompt&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;h4&gt;Application Code&lt;/h4&gt;
&lt;p&gt;Add the code below which will create a Flask Application with impeccable music taste.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ tree -L 4
.
├── app
│   ├── api
│   │   ├── __init__.py
│   │   └── resources.py
│   └── __init__.py
└── run.py&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-python&quot;&gt;&lt;code&gt;&lt;span class=&quot;token comment&quot;&gt;# app/api/resources.py&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; flask &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Blueprint
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; flask &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; jsonify

api &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Blueprint&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;api&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; __name__&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

@api&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;route&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/artists&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; methods&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;GET&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;POST&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;handle_artists&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;method &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;POST&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;ok&apos;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; jsonify&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;name&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;enya&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-python&quot;&gt;&lt;code&gt;&lt;span class=&quot;token comment&quot;&gt;# app/api/__init__.py&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;resources &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; api
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-python&quot;&gt;&lt;code&gt;&lt;span class=&quot;token comment&quot;&gt;# app/__init__.py&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;create_app&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Flask&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    app &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Flask&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;__name__&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;api &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; api &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; api_blueprint
    app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;register_blueprint&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;api_blueprint&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; app
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-python&quot;&gt;&lt;code&gt;&lt;span class=&quot;token comment&quot;&gt;# run.py&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; flask &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Flask
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; app &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; create_app

http_server &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; create_app&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Flask&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Complete application code available at the &lt;a href=&quot;https://github.com/techjacker/python-serverless-api&quot;&gt;example repository&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;Run the App&lt;/h4&gt;
&lt;p&gt;Run the app in local development mode.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ FLASK_DEBUG=1 FLASK_APP=run.py flask run&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;h4&gt;Test the App&lt;/h4&gt;
&lt;p&gt;In another terminal window manually test the API.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ http-prompt localhost:5000

http://localhost:5000&gt; get artists

HTTP/1.0 200 OK
Content-Length: 31
Content-Type: application/json
Date: Thu, 12 Apr 2018 19:15:56 GMT
Server: Werkzeug/0.14.1 Python/3.6.5

[
    {
        &quot;name&quot;: &quot;enya&quot;
    }
]&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;h2&gt;2. &lt;a name=&quot;make-app-serverless&quot;&gt;&lt;/a&gt;Make the Application Serverless&lt;/h2&gt;
&lt;p&gt;Up to this point this is just another Flask application. Time to make it serverless. Add another file called &lt;code&gt;run-lambda.py&lt;/code&gt; to the root of the project.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-python&quot;&gt;&lt;code&gt;&lt;span class=&quot;token comment&quot;&gt;# run-lambda.py&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; flask_lambda &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; FlaskLambda
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; app &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; create_app

http_server &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; create_app&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;FlaskLambda&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;That’s it! Your application is now ready be run on AWS Lambda. The trick here is using &lt;a href=&quot;https://github.com/sivel/flask-lambda&quot;&gt;FlaskLambda&lt;/a&gt; instead of normal Flask. FlaskLambda converts the payload that AWS feeds your Lambda function into the format that Flask expects.&lt;/p&gt;
&lt;p&gt;This adaptor pattern is the same one that &lt;a href=&quot;https://github.com/Miserlou/Zappa&quot;&gt;zappa&lt;/a&gt; uses. Personally I prefer not to introduce any extra tooling dependencies and instead opt for Terraform or &lt;a href=&quot;https://aws.amazon.com/about-aws/whats-new/2016/11/introducing-the-aws-serverless-application-model/&quot;&gt;AWS Serverless Application Model (SAM)&lt;/a&gt; for deployment.&lt;/p&gt;
&lt;p&gt;Be aware that FlaskLambda only supports Python &amp;#x3C;= 3.5. I’ve created a &lt;a href=&quot;https://github.com/techjacker/flask-lambda&quot;&gt;fork&lt;/a&gt; that adds support for Python 3.6+ which you installed earlier with &lt;code&gt;pip install flask-lambda-python36&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;3. &lt;a name=&quot;bundle-app&quot;&gt;&lt;/a&gt;Package Application into Zip for Lambda&lt;/h2&gt;
&lt;p&gt;In order to deploy your application you need to package your application into a zip. The following script which will bundle your application code and dependencies.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;token comment&quot;&gt;# bundlelambda.sh&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#!/usr/bin/env bash&lt;/span&gt;

OUTPUT_ZIP&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$PWD&lt;/span&gt;/terraform/flask-app.zip&quot;&lt;/span&gt;
ARCHIVE_TMP&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/tmp/lambda-bundle-tmp.zip&quot;&lt;/span&gt;

addToZip&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    local exclude_packages&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;setuptools pip easy_install&quot;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;zip&lt;/span&gt; -r9 s&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$ARCHIVE_TMP&lt;/span&gt;&quot;&lt;/span&gt; \
        --exclude ./*.pyc \
        --exclude &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$exclude_packages&lt;/span&gt;&quot;&lt;/span&gt; \
        -- &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${@}&lt;/span&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
addDependencies&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    local packages_dir&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    packages_dir+&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;$(&lt;/span&gt;python -c &lt;span class=&quot;token string&quot;&gt;&quot;from distutils.sysconfig import get_python_lib; print(get_python_lib())&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;))&lt;/span&gt;
    env_packages&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;$(&lt;/span&gt;python -c &lt;span class=&quot;token string&quot;&gt;&quot;from distutils.sysconfig import get_python_lib; print(get_python_lib(plat_specific=1))&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$env_packages&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${packages_dir[0]}&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
        packages_dir+&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$env_packages&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;((&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;${#packages_dir[@]}&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;))&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; -d &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${packages_dir[$i]}&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${packages_dir[$i]}&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; addToZip -- *
    &lt;span class=&quot;token keyword&quot;&gt;done&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$ARCHIVE_TMP&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$OUTPUT_ZIP&lt;/span&gt;&quot;&lt;/span&gt;
addDependencies
addToZip app ./*.py
&lt;span class=&quot;token function&quot;&gt;mv&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$ARCHIVE_TMP&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$OUTPUT_ZIP&lt;/span&gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;This is a simplified version of &lt;a href=&quot;https://github.com/techjacker/python-serverless-api/blob/master/bin/bundlelambda&quot;&gt;the script in the example repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Save and run the script to create a zip bundle at &lt;code&gt;terraform/flask-app.zip&lt;/code&gt;. Ensure you run this on a Linux platform to ensure compatibility with the Lambda runtime environment.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ &lt;span class=&quot;token function&quot;&gt;chmod&lt;/span&gt; +x bundlelambda.sh
$ ./bundlelambda.sh
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;h2&gt;4. &lt;a name=&quot;deploy-app&quot;&gt;&lt;/a&gt;Deploy with &lt;a href=&quot;https://www.terraform.io/&quot;&gt;Terraform&lt;/a&gt;&lt;/h2&gt;
&lt;h4&gt;Terraform Config&lt;/h4&gt;
&lt;p&gt;We will use the &lt;a href=&quot;https://registry.terraform.io/modules/techjacker/lambda-api-gateway/aws/1.0.2&quot;&gt;&lt;code&gt;lambda-api-gateway&lt;/code&gt;&lt;/a&gt; terraform module to handle deployment. Create the Terraform configuration file at &lt;code&gt;terraform/main.tf&lt;/code&gt; and update the &lt;code&gt;account_id&lt;/code&gt; with your AWS account ID.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-hcl&quot;&gt;&lt;code&gt;# terraform/main.tf
module &quot;lambda_api_gateway&quot; {
    source               = &quot;git@github.com:techjacker/terraform-aws-lambda-api-gateway&quot;

    # tags
    project              = &quot;todo-mvc&quot;
    service              = &quot;acme-corp&quot;
    owner                = &quot;Roadrunner&quot;
    costcenter           = &quot;acme-abc&quot;

    # vpc
    vpc_cidr             = &quot;10.0.0.0/16&quot;
    public_subnets_cidr  = [&quot;10.0.1.0/24&quot;, &quot;10.0.2.0/24&quot;]
    private_subnets_cidr = [&quot;10.0.3.0/24&quot;, &quot;10.0.4.0/24&quot;]
    nat_cidr             = [&quot;10.0.5.0/24&quot;, &quot;10.0.6.0/24&quot;]
    igw_cidr             = &quot;10.0.8.0/24&quot;
    azs                  = [&quot;eu-west-1a&quot;, &quot;eu-west-1b&quot;]

    # lambda
    lambda_zip_path      = &quot;flask-app.zip&quot;
    lambda_handler       = &quot;run_lambda.http_server&quot;
    lambda_runtime       = &quot;python3.6&quot;
    lambda_function_name = &quot;HttpWebserver&quot;

    # API gateway
    region               = &quot;eu-west-1&quot;
    account_id           = &quot;123456789&quot;
}&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;The key value here is &lt;code&gt;lambda_handler&lt;/code&gt; which instructs AWS Lambda to use the &lt;code&gt;run_lambda.py&lt;/code&gt; file as the entrypoint to our app.&lt;/p&gt;
&lt;h4&gt;Deploy&lt;/h4&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ &lt;span class=&quot;token function&quot;&gt;cd&lt;/span&gt; terraform
$ terraform apply
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;When complete, Terraform should output the API URL which you can use to manually test the deplopment succeeded.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ http-prompt &lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;terraform output api_url&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
GET artists

HTTP/1.0 200 OK
Content-Length: 31
Content-Type: application/json
Date: Thu, 12 Apr 2018 19:15:56 GMT
Server: Werkzeug/0.14.1 Python/3.6.5

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;enya&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;We took an existing Flask application and turned it serverless with just three lines of code! By using the adaptor pattern we have given ourselves the freedom to easily swap serverless cloud providers in the future. We could even switch to a container based deployment without having to change any of the application code.&lt;/p&gt;
&lt;p&gt;Benefits of this approach:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Develop locally like you always have (no need for emulators)&lt;/li&gt;
&lt;li&gt;Complete visibility into and control over your infrastructure&lt;/li&gt;
&lt;li&gt;Avoids cloud vendor lock-in&lt;/li&gt;
&lt;li&gt;Avoids application code framework lock-in&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Future posts will cover &lt;a href=&quot;https://aws.amazon.com/about-aws/whats-new/2016/11/introducing-the-aws-serverless-application-model/&quot;&gt;AWS Serverless Application Model (SAM)&lt;/a&gt;, Azure Functions and Google Cloud Function deployments.&lt;/p&gt;
&lt;p&gt;Full code for this tutorial available on &lt;a href=&quot;https://github.com/techjacker/python-serverless-api&quot;&gt;github&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How to Send Lightning Payments using the Terminal]]></title><description><![CDATA[In this guide I’m going to walk you through making a payment using Bitcoin’s Layer 2  Lightning Network  using  testnet  to demonstrate. We…]]></description><link>https://andrewgriffithsonline.com/blog/guide-to-make-lightning-network-payments</link><guid isPermaLink="false">https://andrewgriffithsonline.com/blog/guide-to-make-lightning-network-payments</guid><category><![CDATA[bitcoin]]></category><category><![CDATA[lightning-network]]></category><category><![CDATA[c-lightning]]></category><pubDate>Mon, 02 Apr 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In this guide I’m going to walk you through making a payment using Bitcoin’s Layer 2 &lt;a href=&quot;https://lightning.network/&quot;&gt;Lightning Network&lt;/a&gt; using &lt;strong&gt;testnet&lt;/strong&gt; to demonstrate. We will be using the command line as I’ve found this to be the most reliable way to use the network and doing so gives you a deeper understanding of how the network operates.&lt;/p&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;p&gt;You have access to a lightning node that: 1. is running &lt;code&gt;bitcoind&lt;/code&gt; and &lt;code&gt;lightningd&lt;/code&gt; and is synced to the testnet blockchain, 2. has blockstream’s &lt;a href=&quot;https://github.com/ElementsProject/lightning&quot;&gt;c-lightning&lt;/a&gt; cli tool, &lt;code&gt;lightning-cli&lt;/code&gt;, installed and accessible in its &lt;code&gt;$PATH&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Check out my &lt;a href=&quot;/blog/180330-how-to-setup-a-lightning-node&quot;&gt;guide to setting up a lightning network node&lt;/a&gt; if you still need to set one up.&lt;/p&gt;
&lt;h2&gt;1. Generate Address and Fund Wallet&lt;/h2&gt;
&lt;h5&gt;Layer 1 BTC transactions = 1. Wait Time = 60 mins.&lt;/h5&gt;
&lt;p&gt;Create a new address.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ lightning-cli newaddr
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Go to the &lt;a href=&quot;https://testnet.manu.backend.hamburg/faucet&quot;&gt;testnet faucet&lt;/a&gt; and send yourself some bitcoin. Tip - use chrome to get that 70% bonus for using IPV6!&lt;/p&gt;
&lt;p&gt;Click on the transaction ID link that will appear just beneath which will take you to the &lt;a href=&quot;https://testnet.blockchain.info/&quot;&gt;blockchain explorer&lt;/a&gt; with details of the transaction.&lt;/p&gt;
&lt;p&gt;You need to wait for 6 confirmations - about 1 hour before the funds show up in your wallet.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ lightning-cli listfunds
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;outputs&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token string&quot;&gt;&quot;txid&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;d30ad72742d5c05343f65a1f78a90191f7b13341ed309cad0297a4e2fd3f0196&quot;&lt;/span&gt;,
			&lt;span class=&quot;token string&quot;&gt;&quot;output&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 1,
			&lt;span class=&quot;token string&quot;&gt;&quot;value&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 64849668,
			&lt;span class=&quot;token string&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;confirmed&quot;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 1600px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 39.156626506024104%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAARlAAAEZQAGA43XUAAABQUlEQVQY021Q207CQBDtp9Doo4nGL/BFwBdDfPYjABMvb/6XjZFAhBYj4g8YHpRy07a7bWd3Z3edlhASwsnJ5GxmzpzJOmfXj0eXt4f1dqXacmstqoWot936jXtRklq1ols5b7rV5nHj7vTq4aRxf1BrOeHrYNH3l37w0+lOvOfvl07Y7YV9fxYMZ8M3qr/vo3j8uQqGy3JyPvAXBQOyOHaDTNulMpE2zNjUWGkLcmPBWmGttnvgWK3XlKhTpXOFgFprY7QGpWKhY1AR2uhjxD1vMu49fXlhMiWn0bhNzvNcCkEeAaCkRKVoh8hzFscaUbKETafxav4HkUS5Sd6AcZ6mGSImnDOeKqVIZ3lGQJLGxJwDSIsUanfN6+nyWgS5Pt0AQBRFAIK6SRLTU5UX7Zr3QghByVJKMjCQjJbg9u/+Adn1onbtVNkwAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;Bitcoin Explorer&quot;
        title=&quot;Bitcoin Explorer&quot;
        src=&quot;/static/blockchain-explorer-testnet-faucet-transaction-a0dfa026cac3bc48c09d6e32bd11d4d8-48f9d.png&quot;
        srcset=&quot;/static/blockchain-explorer-testnet-faucet-transaction-a0dfa026cac3bc48c09d6e32bd11d4d8-3840e.png 400w,
/static/blockchain-explorer-testnet-faucet-transaction-a0dfa026cac3bc48c09d6e32bd11d4d8-8d40e.png 800w,
/static/blockchain-explorer-testnet-faucet-transaction-a0dfa026cac3bc48c09d6e32bd11d4d8-48f9d.png 1600w,
/static/blockchain-explorer-testnet-faucet-transaction-a0dfa026cac3bc48c09d6e32bd11d4d8-51390.png 1660w&quot;
        sizes=&quot;(max-width: 1600px) 100vw, 1600px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;h2&gt;2. Connect to a Peer and Create a Payment Channel&lt;/h2&gt;
&lt;h5&gt;Layer 1 BTC transactions = 1. Wait Time = 60 mins.&lt;/h5&gt;
&lt;p&gt;In order to make payments on the network you first need to connect to it. How do you find another node to connect to? Head to Acinq’s &lt;a href=&quot;https://explorer.acinq.co&quot;&gt;lightning network explorer&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Search for a well connected peer (one with a lot of channels) and copy its URI. I timed out on a few nodes initially, just keep trying and you’ll find one that connects immediately.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ lightning-cli connect 03e5f9d1935c67a029bf0a26af5f63109f4f4c45993a8f45177a8f2f39bcb46144 77.58.162.148 9735

$ lightning-cli list peers
		&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token string&quot;&gt;&quot;state&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;GOSSIPING&quot;&lt;/span&gt;,
			&lt;span class=&quot;token string&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;03e5f9d1935c67a029bf0a26af5f63109f4f4c45993a8f45177a8f2f39bcb46144&quot;&lt;/span&gt;,
			&lt;span class=&quot;token string&quot;&gt;&quot;alias&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;IslandDSP&quot;&lt;/span&gt;,
			&lt;span class=&quot;token string&quot;&gt;&quot;netaddr&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
				&lt;span class=&quot;token string&quot;&gt;&quot;84.246.200.122:9735&quot;&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;,
			&lt;span class=&quot;token string&quot;&gt;&quot;connected&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Now we will create a payment channel with the peer we just connected to. Opening and closing channels entails interacting with the main blockchain so we want to fund it with a decent amount (in millisatoshis) so that we can use it for several payments.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ lightning-cli fundchannel 03e5f9d1935c67a029bf0a26af5f63109f4f4c45993a8f45177a8f2f39bcb46144 50000

$ lightning-cli listpeers
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token string&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;03e5f9d1935c67a029bf0a26af5f63109f4f4c45993a8f45177a8f2f39bcb46144&quot;&lt;/span&gt;,
			&lt;span class=&quot;token string&quot;&gt;&quot;connected&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; true,
			&lt;span class=&quot;token string&quot;&gt;&quot;netaddr&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
				&lt;span class=&quot;token string&quot;&gt;&quot;84.246.200.122:9735&quot;&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;,
			&lt;span class=&quot;token string&quot;&gt;&quot;alias&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;IslandDSP&quot;&lt;/span&gt;,
			&lt;span class=&quot;token string&quot;&gt;&quot;color&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;68f442&quot;&lt;/span&gt;,
			&lt;span class=&quot;token string&quot;&gt;&quot;channels&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
				&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
					&lt;span class=&quot;token string&quot;&gt;&quot;state&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;CHANNELD_AWAITING_LOCKIN&quot;&lt;/span&gt;,
					&lt;span class=&quot;token string&quot;&gt;&quot;owner&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;lightning_channeld&quot;&lt;/span&gt;,
					&lt;span class=&quot;token string&quot;&gt;&quot;channel_id&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;958b3bd04adb40fd8ff0700a0b24e0298a2ac265273c08ed0218af38140ba678&quot;&lt;/span&gt;,
					&lt;span class=&quot;token string&quot;&gt;&quot;funding_txid&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;78a60b1438af1802ed083c2765c22a8a29e0240b0a70f08ffd40db4ad03b8b95&quot;&lt;/span&gt;,
					&lt;span class=&quot;token string&quot;&gt;&quot;msatoshi_to_us&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 500000000,
					&lt;span class=&quot;token string&quot;&gt;&quot;msatoshi_total&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 500000000,
					&lt;span class=&quot;token string&quot;&gt;&quot;dust_limit_satoshis&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 546,
					&lt;span class=&quot;token string&quot;&gt;&quot;max_htlc_value_in_flight_msat&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 18446744073709552000,
					&lt;span class=&quot;token string&quot;&gt;&quot;channel_reserve_satoshis&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 0,
					&lt;span class=&quot;token string&quot;&gt;&quot;htlc_minimum_msat&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 0,
					&lt;span class=&quot;token string&quot;&gt;&quot;their_to_self_delay&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 6,
					&lt;span class=&quot;token string&quot;&gt;&quot;our_to_self_delay&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 144,
					&lt;span class=&quot;token string&quot;&gt;&quot;to_self_delay&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 6,
					&lt;span class=&quot;token string&quot;&gt;&quot;max_accepted_htlcs&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 483,
					&lt;span class=&quot;token string&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
						&lt;span class=&quot;token string&quot;&gt;&quot;CHANNELD_AWAITING_LOCKIN:Funding needs more confirmations.&quot;&lt;/span&gt;
					&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;,
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Again, search for the &lt;code&gt;txid&lt;/code&gt; in the &lt;a href=&quot;https://testnet.blockchain.info/&quot;&gt;bitcoin testnet explorer&lt;/a&gt; and wait for 3-6 confirmations before the channel is considered open. When it is you should see the status changed to &lt;code&gt;CHANNELD_NORMAL&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ lightning-cli listpeers
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;peers&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token string&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;03e5f9d1935c67a029bf0a26af5f63109f4f4c45993a8f45177a8f2f39bcb46144&quot;&lt;/span&gt;,
			&lt;span class=&quot;token string&quot;&gt;&quot;connected&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; true,
			&lt;span class=&quot;token string&quot;&gt;&quot;netaddr&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
				&lt;span class=&quot;token string&quot;&gt;&quot;84.246.200.122:9735&quot;&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;,
			&lt;span class=&quot;token string&quot;&gt;&quot;alias&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;IslandDSP&quot;&lt;/span&gt;,
			&lt;span class=&quot;token string&quot;&gt;&quot;color&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;3399ff&quot;&lt;/span&gt;,
			&lt;span class=&quot;token string&quot;&gt;&quot;channels&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
				&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
					&lt;span class=&quot;token string&quot;&gt;&quot;state&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;CHANNELD_NORMAL&quot;&lt;/span&gt;,
					&lt;span class=&quot;token string&quot;&gt;&quot;owner&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;lightning_channeld&quot;&lt;/span&gt;,
					&lt;span class=&quot;token string&quot;&gt;&quot;short_channel_id&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1289768:416:0&quot;&lt;/span&gt;,
					&lt;span class=&quot;token string&quot;&gt;&quot;channel_id&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ba95c71228ce3f57e25f6ac9c4a7418a52a056435b2276dd47437c7521ebda8e&quot;&lt;/span&gt;,
					&lt;span class=&quot;token string&quot;&gt;&quot;funding_txid&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;8edaeb21757c4347dd76225b4356a0528a41a7c4c96a5fe2573fce2812c795ba&quot;&lt;/span&gt;,
					&lt;span class=&quot;token string&quot;&gt;&quot;msatoshi_to_us&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 100000000,
					&lt;span class=&quot;token string&quot;&gt;&quot;msatoshi_total&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 100000000,
					&lt;span class=&quot;token string&quot;&gt;&quot;dust_limit_satoshis&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 546,
					&lt;span class=&quot;token string&quot;&gt;&quot;max_htlc_value_in_flight_msat&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 18446744073709552000,
					&lt;span class=&quot;token string&quot;&gt;&quot;channel_reserve_satoshis&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 0,
					&lt;span class=&quot;token string&quot;&gt;&quot;htlc_minimum_msat&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 0,
					&lt;span class=&quot;token string&quot;&gt;&quot;their_to_self_delay&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 6,
					&lt;span class=&quot;token string&quot;&gt;&quot;our_to_self_delay&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 144,
					&lt;span class=&quot;token string&quot;&gt;&quot;to_self_delay&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 6,
					&lt;span class=&quot;token string&quot;&gt;&quot;max_accepted_htlcs&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 483,
					&lt;span class=&quot;token string&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
						&lt;span class=&quot;token string&quot;&gt;&quot;CHANNELD_NORMAL:Funding transaction locked. Channel announced.&quot;&lt;/span&gt;
					&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;,
					&lt;span class=&quot;token string&quot;&gt;&quot;in_payments_offered&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 0,
					&lt;span class=&quot;token string&quot;&gt;&quot;in_msatoshi_offered&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 0,
					&lt;span class=&quot;token string&quot;&gt;&quot;in_payments_fulfilled&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 0,
					&lt;span class=&quot;token string&quot;&gt;&quot;in_msatoshi_fulfilled&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 0,
					&lt;span class=&quot;token string&quot;&gt;&quot;out_payments_offered&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 0,
					&lt;span class=&quot;token string&quot;&gt;&quot;out_msatoshi_offered&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 0,
					&lt;span class=&quot;token string&quot;&gt;&quot;out_payments_fulfilled&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 0,
					&lt;span class=&quot;token string&quot;&gt;&quot;out_msatoshi_fulfilled&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 0
				&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 1600px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 40.973312401883824%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAAsSAAALEgHS3X78AAABP0lEQVQY01WQbW+CMBSF+bgXpa2okUmAUqQglBYpbETn5ssH58z2d8x+/VohC0ue3Nyc3JN77zEswhUQ58DPgcfQQo5oZcUSEaEVP4eYo0BMiCjZ+q1+lWnFqRSxZFFpmH5u3oY6PAa8zFS1L950TIrr9ed99+E4S0IExtzoe9peOU0304rPuqr2eywI+HF/Tpf13ElcN3W9tDOjsEK0AWENo8ZKNLf+BYY1IFKdhjBPlptF+EyjZi0OW3Hc8IPRroWhHIuTJU6DZDcpT0/NN8yOKDugdD+KGj0QFLPicyou4/w8X33Z/DJlZ+PvK0hKGNUAc5NIEG8hXasrFCBok2OPNnmwA8XdDN/bgcLopcL09KLWX9AGhpWpUsBcNSAo1PKhEw/mVOPQtvlvJiuAhQ5JVcw7XV2kdD8fak/U5xcJ7EKmmmfxXgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;Lightning Network Explorer&quot;
        title=&quot;Lightning Network Explorer&quot;
        src=&quot;/static/lightning-network-explorer-smaller-2cc1f8b494a452a254c22b260712f3e0-48f9d.png&quot;
        srcset=&quot;/static/lightning-network-explorer-smaller-2cc1f8b494a452a254c22b260712f3e0-3840e.png 400w,
/static/lightning-network-explorer-smaller-2cc1f8b494a452a254c22b260712f3e0-8d40e.png 800w,
/static/lightning-network-explorer-smaller-2cc1f8b494a452a254c22b260712f3e0-48f9d.png 1600w,
/static/lightning-network-explorer-smaller-2cc1f8b494a452a254c22b260712f3e0-5550c.png 1911w&quot;
        sizes=&quot;(max-width: 1600px) 100vw, 1600px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;h2&gt;3. Generate Payment Request&lt;/h2&gt;
&lt;p&gt;Now we have a confirmed channel established we can start using the lightning network for transactions.&lt;/p&gt;
&lt;p&gt;Go to an article on &lt;a href=&quot;https://yalls.org&quot;&gt;Y’alls&lt;/a&gt; and click on the “continue reading” button to generate a payment request. This is essentially a serialised invoice. Decode it to check that you are not being overcharged!&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ lightning-cli decodepay lntb1500n1pdvp7t9pp5k5mvp8u045pdnumnt89cdc7l90lpvff7sjzkrvawg93ju3mgg3nsdp62fjkzepqg9e8g6trd3jn5gzfyp9kummhyptksmeq2dshgmmndp5jqjtnp5cqzyskw8lzg7w4hcfyhncczcaexlpx3tdefm0vjnh9dkqev23g94tdta8jjqzp87v6r9q8xwe3mnjf0tryaa7zkxxj4gwgfcqea32j0x069qqsjyjhz
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;currency&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;tb&quot;&lt;/span&gt;,
	&lt;span class=&quot;token string&quot;&gt;&quot;timestamp&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 1522596197,
	&lt;span class=&quot;token string&quot;&gt;&quot;created_at&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 1522596197,
	&lt;span class=&quot;token string&quot;&gt;&quot;expiry&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 3600,
	&lt;span class=&quot;token string&quot;&gt;&quot;payee&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;039cc950286a8fa99218283d1adc2456e0d5e81be558da77dd6e85ba9a1fff5ad3&quot;&lt;/span&gt;,
	&lt;span class=&quot;token string&quot;&gt;&quot;msatoshi&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 150000,
	&lt;span class=&quot;token string&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Read Article: I Know Who Satoshi Is\r&quot;&lt;/span&gt;,
	&lt;span class=&quot;token string&quot;&gt;&quot;min_final_cltv_expiry&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 144,
	&lt;span class=&quot;token string&quot;&gt;&quot;payment_hash&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;b536c09f8fad02d9f37359cb86e3df2bfe16253e848561b3ae41632e47684467&quot;&lt;/span&gt;,
	&lt;span class=&quot;token string&quot;&gt;&quot;signature&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;3045022100b38ff123ceadf0925e78c0b1dc9be13456dca76f64a772b6c0cb151416ab6afa022079480209fccd0ca0399d98ee724bd63277be158c69550e42700cf62a93ccfd14&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 896px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 52.56696428571429%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsSAAALEgHS3X78AAAByklEQVQoz2MwsXIwtrQ3t3W2tHcFIiADDzKzcQKqhyMGS3u3jp5+D99gT/8Qd99ga0cPa0d3IGnl6G7lAGLYOHvaOHmAkSfQdBNLe4RmoGFR8al2Lp6WDq7WIA1uFnYulvYuEIcAZYHuQkYoNgOxu29QeExiSGRcaFR8RExiYFhMbGJaZFxSaFSCu0+QkYUdsgZ0zY7uPq5eAUAjXLz8gcjVOxDkPJgKUyAJsRBIwhFMs72JtYuRlbuxtbsREFm5mdsCg80J6GA0ZG5tZ24DQmbWULcwGFk6ubqYhPtpBntrh/hoh/poW1iZ6BhZ6ptYAJGeMQjpA0kTSx1TRx0TJ20TJ10zR6hmdQOHGc3Wbw9bX9pof3Wz3dUtdoXFcW6hWf7RGT5RGb5RGX4gMjMwKjEq2Dw21Dg+zCTIzxyqWUPPpG/SrPN3Py04+Hrx4bdLDr9deez16hOv1px8ver4q1UgxssVJz7uOnX27jq528u5Xm/m2jFJAuZsC3sHV2+vgDCvoEjvoEivwAjPgAgg6RUY6ekf4RUAZgRFefiHevt6OrrY2zva2DjYIUIbGBkGZjaGqMjAzsbAEYzMYSLmDoYWjgYWjkASohkAW9zDcKUUM+AAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;Y&apos;alls Payment Request&quot;
        title=&quot;Y&apos;alls Payment Request&quot;
        src=&quot;/static/yalls-payment-request-area-35c9abfb19304410dab4d4b5eb98d08b-b91d8.png&quot;
        srcset=&quot;/static/yalls-payment-request-area-35c9abfb19304410dab4d4b5eb98d08b-15c3f.png 400w,
/static/yalls-payment-request-area-35c9abfb19304410dab4d4b5eb98d08b-ce1da.png 800w,
/static/yalls-payment-request-area-35c9abfb19304410dab4d4b5eb98d08b-b91d8.png 896w&quot;
        sizes=&quot;(max-width: 896px) 100vw, 896px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;h2&gt;4. Make the Payment&lt;/h2&gt;
&lt;h5&gt;Layer 2 BTC transactions = 1. Wait Time = milliseconds.&lt;/h5&gt;
&lt;p&gt;Now we have everything in place to make a layer 2 bitcoin transaction which should be instantly confirmed.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ lightning-cli pay lntb1500n1pdvp7t9pp5k5mvp8u045pdnumnt89cdc7l90lpvff7sjzkrvawg93ju3mgg3nsdp62fjkzepqg9e8g6trd3jn5gzfyp9kummhyptksmeq2dshgmmndp5jqjtnp5cqzyskw8lzg7w4hcfyhncczcaexlpx3tdefm0vjnh9dkqev23g94tdta8jjqzp87v6r9q8xwe3mnjf0tryaa7zkxxj4gwgfcqea32j0x069qqsjyjhz
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;code&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 206,
	&lt;span class=&quot;token string&quot;&gt;&quot;message&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Fee 1100 is 0.733333% of payment 150000; max fee requested is 0.500000%&quot;&lt;/span&gt;,
	&lt;span class=&quot;token string&quot;&gt;&quot;data&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token string&quot;&gt;&quot;fee&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 1100,
		&lt;span class=&quot;token string&quot;&gt;&quot;feepercent&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 0.733333,
		&lt;span class=&quot;token string&quot;&gt;&quot;msatoshi&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 150000,
		&lt;span class=&quot;token string&quot;&gt;&quot;maxfeepercent&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 0.500000,
		&lt;span class=&quot;token string&quot;&gt;&quot;getroute_tries&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 6,
		&lt;span class=&quot;token string&quot;&gt;&quot;sendpay_tries&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 0,
		&lt;span class=&quot;token string&quot;&gt;&quot;failures&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Go back to Y’alls and click on the “check for payment” button to reveal the article. Unfortunately this didn’t work for me. When I checked on the command line I discovered that indeed no payments had been made.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ lightning-cli listpayments
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;payments&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;To try to solve this issue, I attempted to create a payment channel with Y’alls directly (their address is listed as “peer” when they create you an invoice to continue reading).&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ lightning-cli connect 039cc950286a8fa99218283d1adc2456e0d5e81be558da77dd6e85ba9a1fff5ad3 34.200.252.146

$ lightning-cli fundchannel 039cc950286a8fa99218283d1adc2456e0d5e81be558da77dd6e85ba9a1fff5ad3 500000
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;code&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; -1,
	&lt;span class=&quot;token string&quot;&gt;&quot;message&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;received ERROR channel 3795216ba4a257a1f36f1062af58b4513ad82dac90d298e45ca83271e67cf1d6: Unacceptable channel constraints: minimum HTLC value is too large: 0&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Apparently this is a &lt;a href=&quot;https://github.com/ElementsProject/lightning/issues/1213&quot;&gt;known bug&lt;/a&gt; with &lt;a href=&quot;https://github.com/lightningnetwork/lnd&quot;&gt;&lt;code&gt;lnd&lt;/code&gt;&lt;/a&gt;, which Y’alls must be using as their lightning daemon.&lt;/p&gt;
&lt;p&gt;As a backup plan we’ll send a payment to ourselves using a web lightning wallet. Go to &lt;a href=&quot;https://htlc.me/&quot;&gt;htlc.me&lt;/a&gt; and generate a wallet and then click on the “receive” tab to request a payment of 0.0001 tBTC ($0.65 tUSD). Copy the serialised invoice and check it before sending payment.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ lightning-cli decodepay lntb100u1pdvzzc4pp5h55942ehdpy5g70sty9mnvt3k2wlvt4ucnctnellau8drhaew8lsdqqcqzyswv3n3vyzx9uua4tjl8ttcp5fp7srn80zywvg4vses6fj4q9n3v846mgkuu648u37venf93znkckadjejvddv04vyq5l2krx486z23ysqhcrxg6
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;currency&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;tb&quot;&lt;/span&gt;,
	&lt;span class=&quot;token string&quot;&gt;&quot;timestamp&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 1522600725,
	&lt;span class=&quot;token string&quot;&gt;&quot;created_at&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 1522600725,
	&lt;span class=&quot;token string&quot;&gt;&quot;expiry&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 3600,
	&lt;span class=&quot;token string&quot;&gt;&quot;payee&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;03193d512b010997885b232ecd6b300917e5288de8785d6d9f619a8952728c78e8&quot;&lt;/span&gt;,
	&lt;span class=&quot;token string&quot;&gt;&quot;msatoshi&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 10000000,
	&lt;span class=&quot;token string&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;,
	&lt;span class=&quot;token string&quot;&gt;&quot;min_final_cltv_expiry&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 144,
	&lt;span class=&quot;token string&quot;&gt;&quot;payment_hash&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;bd285aab3768494479f0590bb9b171b29df62ebcc4f0b9e7ffef0ed1dfb971ff&quot;&lt;/span&gt;,
	&lt;span class=&quot;token string&quot;&gt;&quot;signature&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;30440220732338b0823179ced572f9d6bc06890fa0399de223988ab21986932a80b38b0f02205d6d16e73553f23e666692c453b62dd6cb32635ac7d584053eab0cd53e84a892&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;This time when I attempted payment I received multiple errors.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ lightning-cli pay lntb100u1pdvzzc4pp5h55942ehdpy5g70sty9mnvt3k2wlvt4ucnctnellau8drhaew8lsdqqcqzyswv3n3vyzx9uua4tjl8ttcp5fp7srn80zywvg4vses6fj4q9n3v846mgkuu648u37venf93znkckadjejvddv04vyq5l2krx486z23ysqhcrxg6
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;failures&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token string&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;FAIL_PAYMENT_REPLY&quot;&lt;/span&gt;,
			&lt;span class=&quot;token string&quot;&gt;&quot;erring_index&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 1,
			&lt;span class=&quot;token string&quot;&gt;&quot;failcode&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 4103&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;However, when I refreshed the &lt;a href=&quot;https://htlc.me/&quot;&gt;htlc.me&lt;/a&gt; web page I saw that the payment had in fact succeeded. Checking in the console confirmed that payment had been made.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ lightning-cli listpayments
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;payments&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token string&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 1,
			&lt;span class=&quot;token string&quot;&gt;&quot;payment_hash&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;bd285aab3768494479f0590bb9b171b29df62ebcc4f0b9e7ffef0ed1dfb971ff&quot;&lt;/span&gt;,
			&lt;span class=&quot;token string&quot;&gt;&quot;destination&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;03193d512b010997885b232ecd6b300917e5288de8785d6d9f619a8952728c78e8&quot;&lt;/span&gt;,
			&lt;span class=&quot;token string&quot;&gt;&quot;msatoshi&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 10000000,
			&lt;span class=&quot;token string&quot;&gt;&quot;msatoshi_sent&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 10002020,
			&lt;span class=&quot;token string&quot;&gt;&quot;timestamp&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 1522601027,
			&lt;span class=&quot;token string&quot;&gt;&quot;created_at&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 1522601027,
			&lt;span class=&quot;token string&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;complete&quot;&lt;/span&gt;,
			&lt;span class=&quot;token string&quot;&gt;&quot;payment_preimage&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;3e75637befbeec9e7056a4103a06d652cd3cdee9134de69799d8b39c6b1f714c&quot;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;We sent a payment and paid just 2020 millisatoshi in transaction fees ($0.00013 USD at the time of writing)!&lt;/p&gt;
&lt;p&gt;Finally, let’s try to connect with &lt;a href=&quot;https://htlc.me/&quot;&gt;htlc.me&lt;/a&gt; directly so we don’t get any console errors when making payment. Copy the &lt;code&gt;payee&lt;/code&gt; id from the &lt;code&gt;decodepay&lt;/code&gt; command output above and search for it in the &lt;a href=&quot;https://explorer.acinq.co/#/n/03193d512b010997885b232ecd6b300917e5288de8785d6d9f619a8952728c78e8&quot;&gt;lightning network explorer&lt;/a&gt;. Copy the URI then connect to it and create a channel.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ lightning-cli connect 03193d512b010997885b232ecd6b300917e5288de8785d6d9f619a8952728c78e8 34.201.11.250 9735

$ lightning-cli fundchannel 03193d512b010997885b232ecd6b300917e5288de8785d6d9f619a8952728c78e8 500000
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Unfortunately we need to wait for the transaction to confirm on the blockchain so that the channel becomes usable.&lt;/p&gt;
&lt;p&gt;An hour later we can see the channel is established - the status is &lt;strong&gt;&lt;code&gt;CHANNELD_NORMAL&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ lightning-cli listpeers
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token string&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;03193d512b010997885b232ecd6b300917e5288de8785d6d9f619a8952728c78e8&quot;&lt;/span&gt;,
		&lt;span class=&quot;token string&quot;&gt;&quot;connected&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; true,
		&lt;span class=&quot;token string&quot;&gt;&quot;netaddr&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
			&lt;span class=&quot;token string&quot;&gt;&quot;34.201.11.250:9735&quot;&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;,
		&lt;span class=&quot;token string&quot;&gt;&quot;alias&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;htlc.me&quot;&lt;/span&gt;,
		&lt;span class=&quot;token string&quot;&gt;&quot;color&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;854cc5&quot;&lt;/span&gt;,
		&lt;span class=&quot;token string&quot;&gt;&quot;channels&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
			&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
				&lt;span class=&quot;token string&quot;&gt;&quot;state&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;CHANNELD_NORMAL&quot;&lt;/span&gt;,
				&lt;span class=&quot;token string&quot;&gt;&quot;owner&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;lightning_channeld&quot;&lt;/span&gt;,
				&lt;span class=&quot;token string&quot;&gt;&quot;short_channel_id&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1289949:56:0&quot;&lt;/span&gt;,
				&lt;span class=&quot;token string&quot;&gt;&quot;channel_id&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;20dd321c23224b2022f62f59602efc311a8ad63c4481fcd210ef8dade88e8064&quot;&lt;/span&gt;,
				&lt;span class=&quot;token string&quot;&gt;&quot;funding_txid&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;64808ee8ad8def10d2fc81443cd68a1a31fc2e60592ff622204b22231c32dd20&quot;&lt;/span&gt;,
				&lt;span class=&quot;token string&quot;&gt;&quot;msatoshi_to_us&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 500000000,
				&lt;span class=&quot;token string&quot;&gt;&quot;msatoshi_total&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 500000000,
				&lt;span class=&quot;token string&quot;&gt;&quot;dust_limit_satoshis&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 546,
				&lt;span class=&quot;token string&quot;&gt;&quot;max_htlc_value_in_flight_msat&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 18446744073709552000,
				&lt;span class=&quot;token string&quot;&gt;&quot;channel_reserve_satoshis&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 0,
				&lt;span class=&quot;token string&quot;&gt;&quot;htlc_minimum_msat&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 0,
				&lt;span class=&quot;token string&quot;&gt;&quot;their_to_self_delay&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 6,
				&lt;span class=&quot;token string&quot;&gt;&quot;our_to_self_delay&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 144,
				&lt;span class=&quot;token string&quot;&gt;&quot;to_self_delay&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 6,
				&lt;span class=&quot;token string&quot;&gt;&quot;max_accepted_htlcs&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 483,
				&lt;span class=&quot;token string&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
					&lt;span class=&quot;token string&quot;&gt;&quot;CHANNELD_NORMAL:Funding transaction locked.&quot;&lt;/span&gt;
				&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;,
				&lt;span class=&quot;token string&quot;&gt;&quot;in_payments_offered&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 0,
				&lt;span class=&quot;token string&quot;&gt;&quot;in_msatoshi_offered&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 0,
				&lt;span class=&quot;token string&quot;&gt;&quot;in_payments_fulfilled&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 0,
				&lt;span class=&quot;token string&quot;&gt;&quot;in_msatoshi_fulfilled&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 0,
				&lt;span class=&quot;token string&quot;&gt;&quot;out_payments_offered&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 0,
				&lt;span class=&quot;token string&quot;&gt;&quot;out_msatoshi_offered&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 0,
				&lt;span class=&quot;token string&quot;&gt;&quot;out_payments_fulfilled&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 0,
				&lt;span class=&quot;token string&quot;&gt;&quot;out_msatoshi_fulfilled&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 0
			&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Now generate another invoice on &lt;a href=&quot;https://htlc.me/&quot;&gt;htlc.me&lt;/a&gt;, this time for 0.00020000 tBTC ($1.31 tUSD).&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ lightning-cli decodepay lntb200u1pdvzvf8pp5tyjfw9ma9uj8hhrhqvmum9vzvaun45qg6mmesu3c08zkhmgl44ssdqqcqzysah4qe4zef3rssusa42cyx0gxxq6q06g50m38w7chz50en80dfh45fj7kdgpx474udehq22mv2pwxfky66kdjdrw88z34w8hjjdjdu6sq6zy2a4
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Finally make the payment.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ lightning-cli pay lntb200u1pdvzvf8pp5tyjfw9ma9uj8hhrhqvmum9vzvaun45qg6mmesu3c08zkhmgl44ssdqqcqzysah4qe4zef3rssusa42cyx0gxxq6q06g50m38w7chz50en80dfh45fj7kdgpx474udehq22mv2pwxfky66kdjdrw88z34w8hjjdjdu6sq6zy2a4
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 2,
	&lt;span class=&quot;token string&quot;&gt;&quot;payment_hash&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;592497177d2f247bdc770337cd958267793ad008d6f798723879c56bed1fad61&quot;&lt;/span&gt;,
	&lt;span class=&quot;token string&quot;&gt;&quot;destination&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;03193d512b010997885b232ecd6b300917e5288de8785d6d9f619a8952728c78e8&quot;&lt;/span&gt;,
	&lt;span class=&quot;token string&quot;&gt;&quot;msatoshi&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 20000000,
	&lt;span class=&quot;token string&quot;&gt;&quot;msatoshi_sent&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 20000000,
	&lt;span class=&quot;token string&quot;&gt;&quot;timestamp&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 1522610489,
	&lt;span class=&quot;token string&quot;&gt;&quot;created_at&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 1522610489,
	&lt;span class=&quot;token string&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;complete&quot;&lt;/span&gt;,
	&lt;span class=&quot;token string&quot;&gt;&quot;payment_preimage&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1e2767675a227c7f8d57252bfe67d6324829c267f3df38396b4d2bb79a27dfd6&quot;&lt;/span&gt;,
	&lt;span class=&quot;token string&quot;&gt;&quot;getroute_tries&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 1,
	&lt;span class=&quot;token string&quot;&gt;&quot;sendpay_tries&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 1,
	&lt;span class=&quot;token string&quot;&gt;&quot;route&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token string&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;03193d512b010997885b232ecd6b300917e5288de8785d6d9f619a8952728c78e8&quot;&lt;/span&gt;,
		&lt;span class=&quot;token string&quot;&gt;&quot;channel&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1289949:56:0&quot;&lt;/span&gt;,
		&lt;span class=&quot;token string&quot;&gt;&quot;msatoshi&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 20000000,
		&lt;span class=&quot;token string&quot;&gt;&quot;delay&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 144
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;,
	&lt;span class=&quot;token string&quot;&gt;&quot;failures&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;This time no console errors. Your web wallet at &lt;a href=&quot;https://htlc.me/&quot;&gt;htlc.me&lt;/a&gt; should immediately detect the payment. You should now be able to make any number of subsequent payments instantly and with similarly low fees until you deplete the funds in your channel or it expires.&lt;/p&gt;
&lt;p&gt;
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 904px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 70.6858407079646%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAIAAACgpqunAAAACXBIWXMAAAsSAAALEgHS3X78AAABc0lEQVQoz6WSy0oDMRSG+xAu1EdwJwpWwbU73VSquFC8rETFhRZ9GKHSVhC1tSuttH0FV0IrVdFeHKetnelkkskkGc9ML9OLFoo/X8IJOX8O5xCP9Q95YAkhWLcsLpjJTZMBjHHBrd6EtplzjgnFBsXEIAZFhBRV+VUu5KSPFymfr0hfWlUnBK7aQD3XDDeAYVAAgm+kVJFS01UbpMIRE9LIaeCaLcHLClGQAZtG9JJSVxA24a0OcEvEwTVDVMa1EpI/ddnk0CO3G/1DwhbvGJglNIykiixVywajjDvD6oMyWkf1t0KxqqqueTgxu5prruBaJBsPZWKR53g4Ews5hDO3vwBp2dh17o5y2jQ/yk+Tl4vzUf/sjW8u6pu+Who/944GZ/oZC3pHzqYmLhZUqjXNOeV9PXm0nT7ZTAU2ksdbqcDaw6E/sbeS2O9hNXGwfL+7kz7VTez2zOCPcQfBIYY/JQaqa2CiPYTWcTC95qFouH4Aq1H2+PrZltUAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;HTLC.me confirmed received payment&quot;
        title=&quot;HTLC.me confirmed received payment&quot;
        src=&quot;/static/htlc_me_received_payment_confirmation-8dea381aacc3e0a422f8adf77427ee91-f3d1f.png&quot;
        srcset=&quot;/static/htlc_me_received_payment_confirmation-8dea381aacc3e0a422f8adf77427ee91-3bf1f.png 400w,
/static/htlc_me_received_payment_confirmation-8dea381aacc3e0a422f8adf77427ee91-a9629.png 800w,
/static/htlc_me_received_payment_confirmation-8dea381aacc3e0a422f8adf77427ee91-f3d1f.png 904w&quot;
        sizes=&quot;(max-width: 904px) 100vw, 904px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;As you can see, the nodes on testnet are sketchy to say the least. The three main lightning software implementations (lnd, c-lightning, eclair) are all still in the early stages of development so it’s not surprising that a few bugs exist. But this should at least give you a flavour of how cheap and fast transactions will be in the future when the network is bigger and the software running it more mature.&lt;/p&gt;
&lt;p&gt;Join the discussion on &lt;a href=&quot;https://hackernoon.com/how-to-send-bitcoin-lightning-network-payments-for-0-00013-usd-fees-1f525153ee9&quot;&gt;medium&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[How to Set Up a Lightning Network Node (4 Easy Steps)]]></title><description><![CDATA[This guide will take you through setting up a machine running ubuntu/debian as a lightning network node. 1. Install Bitcoind 2. Install C…]]></description><link>https://andrewgriffithsonline.com/blog/180330-how-to-setup-a-lightning-node</link><guid isPermaLink="false">https://andrewgriffithsonline.com/blog/180330-how-to-setup-a-lightning-node</guid><category><![CDATA[bitcoin]]></category><category><![CDATA[lightning-network]]></category><pubDate>Fri, 30 Mar 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This guide will take you through setting up a machine running ubuntu/debian as a lightning network node.&lt;/p&gt;
&lt;h2&gt;1. Install Bitcoind&lt;/h2&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; add-apt-repository -y ppa:bitcoin/bitcoin
$ &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt-get&lt;/span&gt; update
$ &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt-get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; -y bitcoind
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;h2&gt;2. Install C-Lightning&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/ElementsProject/lightning&quot;&gt;c-lightning&lt;/a&gt; is blockstream’s lightning network daemon.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt-get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; -y \
	autoconf automake build-essential &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; libtool libgmp-dev \
	libsqlite3-dev python python3 net-tools
$ &lt;span class=&quot;token function&quot;&gt;cd&lt;/span&gt; /opt
$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; clone https://github.com/ElementsProject/lightning.git lightningd
$ &lt;span class=&quot;token function&quot;&gt;cd&lt;/span&gt; lightningd
$ &lt;span class=&quot;token function&quot;&gt;make&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;h2&gt;3. Configure Bitcoind and C-Lightning&lt;/h2&gt;
&lt;p&gt;Create a file at &lt;strong&gt;&lt;code&gt;~/.lightning/config&lt;/code&gt;&lt;/strong&gt; with the following contents.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-ini&quot;&gt;&lt;code&gt;# network&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;testnet # uncomment to run on testnet instead of mainnet&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Create a file at &lt;strong&gt;&lt;code&gt;~/.bitcoin/bitcoin.conf&lt;/code&gt;&lt;/strong&gt; with the following contents.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-ini&quot;&gt;&lt;code&gt;# testnet&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;1 # uncomment to run on testnet instead of mainnet&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;printtoconsole&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;1&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;1&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;txindex&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;h2&gt;4. Sync with the blockchain&lt;/h2&gt;
&lt;p&gt;This step will take 1-4 hours depending upon the speed of your internet connection.&lt;/p&gt;
&lt;p&gt;Run the bitcoin daemon.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ bitcoind -daemon
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;In another terminal window run the lightning daemon.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ lightningd
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Check everything is running correctly.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-shell&quot;&gt;&lt;code&gt;$ lightning-cli -H getinfo
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;07798d536c58ede3d3a150ba89679e2dc78a3a0966074024ad4081367abda76719&quot;&lt;/span&gt;,
	&lt;span class=&quot;token string&quot;&gt;&quot;port&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 9735,
	&lt;span class=&quot;token string&quot;&gt;&quot;address&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;token string&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ipv6&quot;&lt;/span&gt;,
			&lt;span class=&quot;token string&quot;&gt;&quot;address&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;edc7:c9f:dc33:5922:21b2:f0d0:2a02:4f40&quot;&lt;/span&gt;,
			&lt;span class=&quot;token string&quot;&gt;&quot;port&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 9735
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;,
	&lt;span class=&quot;token string&quot;&gt;&quot;version&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;v0.5.2-2016-11-21-2438-g1fe79df&quot;&lt;/span&gt;,
	&lt;span class=&quot;token string&quot;&gt;&quot;blockheight&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; 1290015,
	&lt;span class=&quot;token string&quot;&gt;&quot;network&quot;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;testnet&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;Check the &lt;strong&gt;&lt;code&gt;blockheight&lt;/code&gt;&lt;/strong&gt; of your target blockchain using &lt;a href=&quot;https://blockchain.info/&quot;&gt;an explorer&lt;/a&gt; to discover how far through the syncing process you are.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;You’ll want to be running your node on machine that is permanently switched on and connected to the internet. Restarting the daemons even after they’ve downloaded the blockchain takes a long time as they have to reindex transactions in memory. Furthermore, you’ll want your node constantly available so it can accept and route payments, earning you BTC.&lt;/p&gt;
&lt;p&gt;Personally I’ve used an old laptop which I leave switched on and connected to my router 24/7. For convenience I’ve set up ssh access to it so I can make payments using it. Check out my guide on &lt;a href=&quot;/blog/guide-to-make-lightning-network-payments&quot;&gt;how to make lightning payments&lt;/a&gt; to learn how to do this.&lt;/p&gt;</content:encoded></item></channel></rss>