Skip to main content

Using your first microservice with AWS Lambda

Posted on August 6, 2018 by PhilZonaPhilZona

Infrastructure can be intimidating. There’s a reason AWS is the most popular cloud platform in the world – it’s complex. That complexity is what allows AWS to be so powerful, but it can also be a huge barrier for people who aren’t already working with similar tools. We’ve talked a lot about the value of knowing the AWS platform, but knowing where to start is a problem of its own. In this guide, I want to go back to the basics of web development and talk about how to use a microservice hosted on AWS. To do this, we’ll create a simple web page that uses a serverless contact form that allows your users to send you emails.

Who is this guide for?

When we talk about learning AWS, we often talk about how you can use it to launch a new career in systems administration or operations. Of course, the platform isn’t only for “backend” or “systems” work. Services like AWS Lambda need to be integrated into the front end, and because AWS is so widely used, it’s important for web developers to have some familiarity with how it works. This guide is for web developers who want to know more about microservice architecture, but aren’t ready to learn the whole AWS platform from the ground up.


The word microservice sounds complex, but you don’t need to be an expert to start working with them. However, you do need a few things to get started:

  • An AWS account – You can create one for free here.
  • A microservice to use – We previously posted a guide on creating a serverless contact form using AWS Lambda. That’s what we’ll be integrating into our page (and we recommend you follow that guide before this one), but the principles and concepts we talk about will apply to other microservices based on AWS Lambda and API Gateway as well.
  • Some JavaScript knowledge – We’ll use JavaScript to interact with our microservice from the browser, so you should be familiar with intermediate-level concepts like DOM interaction and AJAX requests to get the most out of this guide.

What will we be making?

In this guide, we’ll be integrating an existing contact form microservice into a web page. Before getting started, make sure to follow our guide on creating a serverless contact form. That guide handles the “backend” setup on AWS, and this guide will explain how to integrate it into an existing site. When we’re done, you’ll have a contact form that calls an AWS Lambda function that allows your users to send you an email through a form on your site.

What is a microservice?

This question could take up a guide of its own, but it’s important to understand before we get started. Microservice architecture means that your infrastructure (the servers that host your app) is made up of small, mostly independent pieces that are each responsible for a specific task. When you write an application, you use functions to perform certain tasks and separate responsibilities within your codebase.
To use a rough analogy, microservices are to infrastructure as functions are to your code.
Let’s say your application crashes. If your codebase is large enough, it could take a ton of work to isolate and fix the issue – and you may not be able to bring your application back online until you do. With a microservice architecture – using separate infrastructure to handle different tasks – you can often leave the rest of the app running while you fix one particular issue. The problem is isolated and has little or no impact on the rest of your code.
You may have heard terms like serverless or functions as a service. Lambda is Amazon’s implementation of these concepts, and a microservice architecture is one way that it can be used to improve your site or application.

Integrating your first microservice

If you haven’t created your infrastructure in AWS, be sure to do that first. Our guide to setting up your serverless contact form can be found here. If you’re creating your first AWS account (or using one created in the last 12 months), all the services we use will be included in the free tier, so it won’t cost you anything to follow along and try it out.
The AWS infrastructure serves as your “backend,” but you also need a form to allow users to input information. Here’s a simple web page that we’ll use to illustrate how to make it work:

If you’d like to follow along, paste the code above into a text editor open it in your browser. You’ll see something like this:
A basic contact form
Now let’s break down each part of the script, step by step. This isn’t meant to be the most efficient implementation, but I wrote out the code to explicitly show all of the component parts. There are frameworks that can do the same thing, but the goal here is to illustrate what’s going on with a series of easy-to-follow steps. We won’t go over the HTML structure of the page, since that part will be up to you when designing your application.
First, we need to enable to form to do something when it gets submitted:

This will probably look familiar – we’re just adding an event listener onto the form. When it gets submitted, the sendDataToLambda function will be called. Further down in the code, we define that function. You can ignore the e.preventDefault() line at the beginning of the function – it prevents the page from reloading on submission, which makes testing easier – and continue down to the first three variables we create:

This part should also look familiar. When the form is submitted, one of the first things we need to do is grab the values of each input field. Because of the way we created our Lambda function, it expects three values: the user’s email address, the subject of the email, and the body of the message.
Up until now we’ve been dealing with concepts you’ve probably seen before, but next, we’ll begin to see how Lambda comes into play.

This line defines our endpoint. If you’ve done much web development, you’ve probably used an API before (Google Maps or Yelp, for example). Our serverless contact form works in a very similar way. When we created our Lambda function, we set the API Gateway service to be its trigger. You can think of API Gateway as a managed API service. It listens for HTTP(S) requests, and does something when it receives them. In this case, it invokes our Lambda function to send an email.
To find your endpoint, navigate to API Gateway in the AWS web console. In the menu on the left, select the “contact” API we created, and click Stages. Select the “prod” stage, and copy the Invoke URL shown in the blue box at the top of the page. That’s the base of your URL – you’ll also need to add a resource. If you followed along in our initial guide, we named this “/ContactFormLambda” but you can find it in the Resources section under your “contact” API if you called it something else.
To summarize, your endpoint is made up of both the invoke URL and the resource name. If you try to run your function from the browser and get a “Missing Authentication Token” error, this is a good place to check first.
Next, we’ll construct an object:

This object is what we’ll use as the body of our HTTP request to the API Gateway. We’re using the three required fields that our Lambda function expects to receive, along with the values we got from our user input fields earlier.
The next step instantiates (creates) our request. This might look unfamiliar, so let’s break down why we’re doing it this way:

This is a Request object, and it’s specific to the Fetch browser API. If you are familiar with AJAX, you may have used jQuery’s .ajax() method or the browser’s native XMLHttpRequest (XHR) object to make server requests. Fetch does most of the same things, but it’s a little more modern and, in my opinion, easier to use.
We’re creating a new instance of Request, which takes two parameters. First, the endpoint where the request will be made (our API Gateway route), and second, an object containing some information about the request. Since we’re sending data to our endpoint, we’re using the “POST” method. We also need to convert the body of our request to a string so that Lambda can understand it (our Lambda function expects a string, but will parse it as JSON when it gets called – see the Lambda code for details on how this happens).
The other setting we’re using, “no-cors” mode, is for local development. It allows us test our code while avoiding some default security features of the Fetch API.  We’ll talk more about what this means in the next section.
Finally, we put everything together into a Fetch call:

This is where we make our request, which is described by the Request object we created above. The second and third lines are where we’d handle errors – this syntax is used because Fetch resolves with a JavaScript Promise. For your application, you’ll probably want to write some custom code here, but we’ll just log the results for the sake of example.
And that’s it! With this code in place, you can enter some test data in the form, and submit it.
Submitting data to the serverless contact form
Once you’ve done that, check the email account you verified with AWS, and you should see a new message with the information you provided:
The email message we receive from AWS
A couple final notes – you will need to enter a valid email address in the email field. SES does validate this section, and you’ll receive an error if it doesn’t detect a valid format. You’ll also notice that, after submitting your form, the response data that is supposed to logged to the console is incomplete. For example, you’ll see a “status” property of 0, rather than the actual HTTP status code (200 or 5xx). This is due to the “no-cors” mode we set on the request, which we’ll address next.

Deploying to production

This setup is fine for testing, or if you just want to see how things work. If you’re ready to start using a serverless contact form on your own site, however, you’ll need to take a couple more steps.
First of all, remove mode: ‘no-cors’  from your Request object. Normally, you can’t make cross-origin requests from your local computer since its origin is set to ‘null.’ Adding this option to the request allows us to test locally, but it’s not necessary to make calls from your own site. In fact, leaving it in production may prevent you from being able to accurately handle errors in the Fetch response – it will cause you to get an opaque (empty) response, and you won’t have access to things like HTTP status codes or error messages.
Finally, change the “Access-Control-Allow-Origin” header in API Gateway to your domain name. To find this setting, open your “/ContactFormLambda” resource in the API Gateway console, click the Actions menu at the top of the page, and select Enable CORS. The last field on this page will allow you to set this header to the domain name of the site on which you’ll use your contact form:
Setting your Access-Control-Allow-Origin header

So why does this matter?

We talked about the benefits of microservice architecture a little bit before – it separates your services so that if one fails, your entire application doesn’t go down. For example, you might create another microservice that reads from your database, in addition to your contact form. If one of these services crash, the other can continue to run without requiring you to log into your server and restart your app.
Another benefit is development speed. A “normal” architecture requires more testing to ensure that new code doesn’t interfere with the existing application. With microservices, a contact email and a database read, for example, are totally independent. You can make changes to one service, test that service, and deploy it immediately. New services can be added at any point without stressing about whether they’ll cause a breaking change.
Microservices, like the contact form we created, are also easy to integrate into static sites. Over the last few years, static site generators have become incredibly popular, and for good reason – they’re fast, maintainable, and make it relatively easy to create a nice-looking site without much code. Microservices allow you to run a backend without all the maintenance that can scare people away from unmanaged hosting. They also provide a nice middle ground when creating your site – maybe you don’t need a full PHP or Rails application, but a static site just doesn’t quite do enough. Microservices with AWS Lambda allow you to handle traditional “server-side” operations by creating scripts like the one above and embedding them into your static pages.

What’s next?

The connection between web development and a complex platform like AWS isn’t always immediately clear. AWS is often thought of as a service for administrators, but with a little bit of knowledge, it’s not too difficult to get started using it in your own projects.
I want to clarify something – what we’ve created here is not a full microservice architecture. It’s just an example of how you might build one and only shows one component. But with AWS Lambda, creating more services like our contact form submission is easier than ever. Because Lambda offers functions as a service, you can focus more on the code and less on the infrastructure that runs it. You can follow our guide on creating a serverless contact form and modify it to perform other tasks for you – sending text messages with AWS Simple Notification Service (SNS) might be a good next step. AWS offers dozens of services, so if you look around, you’re sure to find something interesting to play with.
The best way to learn is by doing. You can read all the documentation in the world, but until you get your hands dirty, it’s difficult to truly develop your skills. If this guide got you excited about the power of AWS, there are plenty of projects you can try out at little or no cost. The microservice we created here is covered under the AWS free tier – which applies to new AWS accounts for 12 months from the date they’re created. AWS also published a static web hosting guide that covers a $0.50 (yes, that’s cents) per month setup. What’s important is getting in there and using the services – the knowledge and skills will come with experience.
Of course, if you want a more formal training program, that’s what we’re here for. Our mission is to help people of all skill levels learn cloud computing through real-world scenarios and hands-on training. Let us know in the comments if you have questions, or better yet, sign up for a free community account and find out where your cloud learning journey will take you.

Further reading

While the scope of this guide was meant to be limited to microservice implementation, we used a few web technologies and concepts that might warrant some extra research. Here are a couple links to get a more in-depth look than we provided here:
That’s So Fetch (credit to Jake Archibald)
Understanding CORS
AWS Lambda Deep Dive


Image of Jay
3 years ago

thanks for the article

Image of Laura Wynn
Laura Wynn
2 years ago

Thank you for the article! I am using this methodology for my high school alums’ contact info form. Question for you. I have tried everything to clear the form after the “sendDataToLambda” and can’t seem to get the form to clear. I have tried the document.getElementById reset and value’ ‘ but nothing is working. Suggestions and where should it go?

Image of Laura Wynn
Laura Wynn
2 years ago

Disregard previous message. I added a script to redirect to the home page upon successful completion.

Image of PhilZona
2 years ago

Hi Laura,
It sounds like you’re trying to reset the form outside the `sendDataToLambda` function. Since this function is what gets called when you submit the form, you’ll want to make sure you’re resetting within that function, but after you get the values. If you try to do it after the `sendDataToLambda` function ends (outside its context), the reset happens on page load instead of when you submit the form – since the inputs are already empty, that would be really tricky to catch. In fact, it would look like your code wasn’t doing anything at all, which I think might be the problem you’re having!
Try this after your `fetch(lambdaRequest)…` call, but before the closing bracket in `sendDataToLambda`:
Here’s what the full code looks like if you’d like to see it in context: updated serverless contact form example
Hope this helps! If you’re still having trouble, let me know and we’ll get it figured out!

Image of Tim Guy
Tim Guy
2 years ago

Thank you so much for these two comprehensive posts. I have it working! 😀 Would it be possible to show an example that displays a message after the form has been sent? Something like “Success!” ? I’ve no idea how to do this… Thanks plenty! Tim

Image of PhilZona
2 years ago

Hey Tim! You’d typically handle this in the fetch callbacks (check out lines 57 and 58 in the sample code). Rather than just logging the response/error to the console, you can take other actions too – the simplest way to show a success message would be to create a separate page for it on your site and use this section to redirect the user there. Here’s a quick example of what I mean:
You can also use this section to trigger a modal (if you have a library installed), for example, but hopefully this gives you a good starting point!

Image of Tim Guy
Tim Guy
2 years ago

Hi Phil. Thanks so much for your super fast help and example. Will give it a shot! 🙂

Image of PhilZona
2 years ago

Glad to help, let me know if you run into any issues and we’ll see if we can figure it out!

Image of Tim Guy
Tim Guy
2 years ago

Your redirect-to-page code works great – thanks! 🙂 Be great to see an example sometime where the message appears under the form itself. That’s beyond my skills I’m afraid… 😉 I went through a few other Lambda microservice tuts that didn’t work. Yours did! Thanks again.

Image of PhilZona
2 years ago

Thanks for the kind words! There are a lot of different ways to generate text on the page, but here’s an example that shows one method:
I added comments to explain what’s going on, but let me know if something in the code isn’t clear. You can also style the success message, give it some nice animations, and all kinds of other cool stuff. For some ideas, I’d recommend looking into DOM manipulation with Javascript. You can use the fetch callbacks to do just about anything you want to the HTML, depending on whether the operation succeeds or fails – your imagination is really the only limit!

Image of dez
2 years ago

First of all, thank you for this great tutorial. It the quickest and easiest I’ve found.
I am hitting a snag though getting your example running in S3. I’ve enabled CORS on the `/ContactFormLambda` resource, added my domain and commented out `mode: ‘no-cors’,` on the request on the contact.html file. I can fill out the form, submit and receive the email successfully, but I’m still getting a console error (I’ve stripped any personal info from the error) :
Access to fetch at ‘https://my-aws-endpoint-blahblah/default/ContactFormLambda’ from origin ‘’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. If an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.
I’ve tried several variations of wildcards in the domain in the Access-Control-Allow-Origin field, but to no avail. Also, I’ve re-deployed the api after making these changes thinking that may be it.
It’s weird, because the email still send successfully. What did I miss?
Thanks again

Image of PhilZona
2 years ago

Great question – since the email is sending, this seems like it’s probably an issue with the response in the browser. I’ve run into similar errors, and resolved them by setting a header manually within the Lambda code like this: I am not totally sure why you need to set up CORS headers on the API Gateway resource as well as on the response from Lambda itself, but I assume it’s there as a security feature. It also has to do with the browser – most browser vendors tend to err on the side of caution when receiving response data due to various XSS vulnerabilities, and it seems like that’s what’s going on here.
The response is only needed if you’re doing something with the data from it, however. For example, you can print a message like “Thanks for your email, I’ll be in touch soon” to the page upon a successful call, and the same thing with error handling. If you don’t need to customize it to that level, you can redirect the user back to another page after the call is made. You can leave in the `mode: ‘no-cors’` line to give an opaque response, meaning that the client will still be able to tell a successful call from a failed one, it just won’t have access to any of the metadata. It really depends what you want your user flow to look like on your site.
Hope this helps, but if not let me know and we’ll figure it out!

Image of Leigh
7 months ago

Hi Phil,

I did the 2 tutorials and it was successful using my local host. However, when I put the index.html code on a wordpress server (spun up on an ec2 instance), I don’t receive an email. Was wondering if you had any input on how to fix this.

Image of Christophe Limpalair
Christophe Limpalair
7 months ago

Hi Leigh, it might be because the EC2 instance security group is blocking emails from going out since it requires ports to be open. Try to look into that, and if it still doesn’t work, try playing around with logging errors to see if anything is happening with the code that’s preventing the email from being sent out!


Leave a Reply

Your email address will not be published. Required fields are marked *