In this tutorial, we will build a serverless payment application with Stripe and AWS Lambda.
Try the Live Demo!
Note that this is a bare-bones implementation and is not production ready.
What is Serverless?
When we say “serverless”, it doesn’t mean servers are no longer involved. It means that you no longer need to think about them.
Serverless is an approach that aims to eliminate the need to manage infrastructure by:
- Using a managed FaaS compute service such as AWS Lambda, Webtask, Google Cloud Functions, and IBM OpenWhisk to execute code,
- Leveraging third-party services and APIs, and
- Applying serverless architectures and patterns.
By making use of third-party services, developers can build loosely coupled, scalable, and efficient architectures quickly. Instead of building things from scratch, we connect prefabricated parts together. Today, we can rely on an abundance of third party services for payments, email, analytics, and many more.
This ecosystem of services accelerates software development. We can focus more on our core value propositions instead of secondary capabilities such as email infrastructure and server maintenance.
Serverless frees the software developer from deployment concerns so you can move fast, iterate quickly, and scale.
FaaS providers such as AWS Lambda offers a new kind of platform that lets you deploy and invoke ephemeral (short-lived) function processes via events to handle individual requests.
Ephemeral function processes are created when an input is received, and disappears after the code finishes executing. The platform handles the provisioning of instances, termination, monitoring, logging, and so on.
Think of Serverless functions as ‘MeeSeeks’ of cloud computing.
Meeseeks are creatures created to serve a singular purpose for which they will go to any length to fulfill. After they serve their purpose, they expire and vanish into the air.
– From the ‘Rick and Morty’ Wiki
Like MeeSeeks, function processes vanish once executed.
Capacity planning in FaaS
With traditional deployments, you can over-provision and under-provision compute capacity. This is especially true when your traffic load is unpredictable.
Image credit to getshifter.io
When you over-provision, you’re wasting money on idle compute time. When you under-provision, you can’t adequately serve your users. Compute capacity is usually over-provisioned, and for good reason.
With FaaS, the provisioned capacity will always be equal to the actual usage. There is no under or over provisioning. Each request spawns an ephemeral function process that executes your function. The FaaS provider handles the horizontal scaling automatically. If your system needs to be processing 100 requests in parallel the provider will spawn that many function invocations without any extra configuration on your part. You only pay for the compute capacity used.
PaaS vs FaaS
The table below highlights the differences between PaaS and Faas:
|Platform-as-a-Service (PaaS)||Function-as-a-Service (FaaS)|
|Startup time||Starts in minutes||Starts in milliseconds|
|Running time||Runs 24 / 7||Runs when processing an incoming request|
|Cost||Monthly billing cycles||Pay for usage, in invocations and duration|
|Unit of code||Monolithic app||Single-purpose, self-contained functions|
In summary, FaaS providers offers developers the ability to build services that react to events, that auto-scale, that you pay for per-execution, and that take advantage of a larger ecosystem of third-party services.
If you’d like to follow along, make sure you’ve completed the following steps.
Stripe is a platform for handling online payments. Make sure that you’ve signed up for Stripe, and access your dashboard.
Test mode and obtain the following from the
- Your publishable API key
- Your secret API key
We need both keys for our application. The publishable API key is used to tokenize customer cards, and the secret API key is used to process charges via the Stripe API.
The Serverless framework (
serverless) is a Node.js command-line interface (CLI) that helps you develop and deploy your serverless functions, along with the infrastructure resources they require.
serverless makes it easy to organize all the relevant resources your application needs in order to run. Write your function code, add event triggers, and deploy it with the help of
serverless to the FaaS provider of your choice. Functions are automatically deployed and events are compiled into the syntax your FaaS provider understands.
serverless is provider and runtime agnostic, so you are free to use any of the supported FaaS providers and languages.
serverless node module with
yarn. In your terminal, do:
Let’s check that
serverless has been installed:
3. Amazon Web Services (AWS)
We’ll be using AWS as our FaaS provider. If you haven’t already, sign up for an AWS account.
The next thing we need to do is to create an AWS user which has administrative access to your account. This lets the Serverless Framework configure the services in your AWS account.
- Login to your AWS account
- Go to the Identity & Access Management (IAM) page
- Click on the Users sidebar link
- Click on the Add user button
- Enter serverless-admin, tick the Programmatic access Access type checkbox, and click Next:Permissions
- Click Attach existing policies directly, tick Administrator Access, and click Next: Review
- Review your choices, then click Create user
- Save the Access key ID and Secret access key of the newly created user
Done! We’ve now created a user which can perform actions in our AWS account on our behalf (thanks to the Administrator Access policy).
Finally, we’ll pass the user’s API Key & Secret to
serverless framework installed on your machine, do:
serverless config credentials --provider aws --key <your_aws_key> --secret <your_aws_secret>
yarn in place of
Using card information with Stripe is a two-step process:
- Securely collect payment information using tokenization (Performed in the Frontend using the Stripe publishable API key)
- Use the payment information in a charge request or save it for later (Performed in the Backend using the Stripe secret API key)
When a user enters their payment information on the Stripe Checkout embeddable form, client-side tokenization occurs.
Client-side tokenization is the method Stripe uses to collect card information directly from your customers in a secure manner. During this process, a token representing this information is returned to your backend server for use in a charge request (or to save the card details for later use). Tokens can only be used once and expire within a few minutes.
Tokenization ensures that no sensitive card data ever needs to touch your server so your integration can operate in a PCI compliant way. If any card data were to pass through or be stored on your server, you would be responsible for any PCI DSS guidelines and audits that are required.
Below is the
PayButton component that is core to our payments flow.
After a successful tokenization request to the Stripe API, we make a POST request containing the token and payment details to a URL where our backend lives.
The token returned by our frontend is used by our backend to process the actual charge (through a Stripe API call.)
Our serverless ‘nanoservice’ is composed of single-purpose, granular functions. The Serverless framework uses a DSL that describes the shape of our services.
Take a look at the
serverless.yml which describes our project:
Our service has a single function
createCharge whose source code is in
/functions/createCharge.js and can be
triggered by HTTP POST events to the
The three key abstractions of
serverlessapplications are Functions, Events, and Resources:
- Functions are pieces of single-purpose code deployed in the cloud. When deciding what should go in a function, think of the Single Responsibility Principle or the Unix philosophy.
- Events are set up to trigger your functions. On AWS, these events include infrastructure events such as an AWS API Gateway HTTP endpoint request (useful for HTTP APIs) and an AWS S3 bucket upload (useful for file uploads).
- Resources are infrastructure components which your Functions communicate with. Because functions are stateless, we need some way to capture and store state (in an AWS DynamoDB table or an AWS S3 bucket for example.)
Next, let’s look at the
createCharge function. This is the function that takes in a Stripe token and uses it to create a Stripe charge:
An AWS Lambda (Node.js) handler function takes takes three arguments:
event– AWS Lambda uses this parameter to pass in event data to the handler.
context– AWS Lambda uses this parameter to provide your handler the runtime information of the Lambda function that is executing.
callback– You can use the optional callback to return information to the caller, otherwise return value is null.
createCharge function, we retrieve the payment details from the HTTP request body and call Stripe’s API to process the charge.
We then return an HTTP response containing the created charge object.
To deploy our
serverless application to AWS, do:
serverless CLI will translate
serverless.yml into a provider specific language such as AWS CloudFormation and set up your cloud infrastructure.
Since we’ve specified an HTTP event trigger for our
createCharge function in
serverless.yml, we get a URL endpoint
https://kpygs0yhak.execute-api.ap-southeast-1.amazonaws.com/dev/charges we can use to trigger our function.
Behind the scenes,
serverless created an AWS API Gateway resource and a mapping between our HTTP route and lambda function.
This is the backend url that our frontend application communicates with.
Since each our functions only does one thing, it’s a unit and by definition unit testable! Check out
Congratulations! You’ve gone serverless!
We’ve built a scalable payments system by leveraging an external compute service and third-party APIs. Along the way, we learned:
- What serverless is about, and why it’s compelling
- How a payment flow works with Stripe on both frontend and backend
- The basic abstractions of serverless: Events, Functions, Resources
- How to create a Serverless backend with Node.js and AWS Lambda
- How to set up event triggers for functions
- How to deploy functions
- How to write and run unit tests
Thank you for reading!
Feel free to clone and check out the source code:
Pull requests and feedback are most welcome.
Get the Book
This article has skipped a fair amount of detail in favour of succinctness. For example, both the example frontend and backend applications has no auth mechanisms set up at all! If you’d like to learn more, check out the Going Serverless book!
Going Serverless is a practical guide to building Scalable applications with the Serverless framework and AWS Lambda. This book will teach you how to design, develop, test, deploy, monitor, and secure Serverless applications from planning to production.
- An event-driven image processing pipeline
- A scalable web scraper
- A serverless microservice
Each hands-on project is a real-life implementation of a serverless design pattern. You’ll also learn how to use a suite of AWS technologies beyond just Lambda such as API Gateway, DynamoDB, SNS, S3, and more.
📬 Get updates straight to your inbox!
Subscribe to my newsletter to make sure you don't miss anything.