This was my very first cloud architecture project and was a blast to work on. Because this was my first time dealing with different AWS services I did run into some issues but the more I worked on this project the more I learned and the skills I gained. This project was about deploying a serverless web application that people could sign up for to get rides from unicorns to and from places, similar to Uber. Below I will get into the details of what I did to make this project work.
To start off, I launched an EC2 instance using Cloud9. Cloud9 is a cloud-based IDE that lets you write, run and debug code, and it has a terminal as well to run some commands. Following the steps given by AWS, I deployed the basic free-level EC2 instance (t2.micro), but as I continued with the project I found out that the EC2 instance I was deploying was not powerful enough to run this project. After much research on the error code I was receiving when trying to install the Amplify CLI I used later in this project, I found out that by deploying the m5.large instance type I was able to run through all of the steps in this project and have it function properly.
Next, after setting up the EC2 instance to run the IDE, I needed to set up a repository for the code provided by AWS. I used AWS CodeCommit to store the code for this project. After running some commands provided by AWS the code was successfully pushed to the CodeCommit repository. I could have easily made the CodeCommit repository from the AWS Management Console GUI but for the majority of this project, I used the AWS CLI from my Cloud9 IDE. The next major step I needed to do was to deploy the code that I had just put in the repository, for this I used AWS Amplify. AWS Amplify is widely used for full-stack applications and is helpful to build and deploy applications front and backend.
Furthermore, the next major section was all about user management. To start, I needed to set up a user pool for people to create accounts to access the portion of the site that allows them to request a ride from a unicorn. So to make this work I used AWS Cognito. Cognito “provides an identity store that scales to millions of users, supports social and enterprise identity federation, and offers advanced security features to protect your consumers and business“. Within Cognito, I created a user pool, so that when a user creates an account, their account is populated in the pool of users. This pool retains their credentials and allows users to verify themselves with MFA codes sent via email.
After confirming that the user pool was created properly with Cognito and making test users, it was now time for the backend of the application. The first step was to create a DynamoDB table. DynamoDB is a “serverless, key-value NoSQL database designed to run high-performance applications at any scale“. I used DynamoDB, in this case, to store the rides and ride information created during the Lambda function that I will discuss next.
After getting the DynamoDB setup, I set up the Lambda function that finishes the “ride request” for this project. AWS Lambda is a “compute service that lets you run code without provisioning or managing servers”. To go more into depth on the Lambda function that was created, I took the code given by AWS and created a new Lambda function. This function selects a unicorn from the options available in the code I stored in CodeCommit and records the ride request in DynamoDB. After it finishes the recording into DynamoDB it responds on the front end of the application to let the “customer” know where the ride pickup location is and what unicorn is on the way. After this function was created, AWS recommended to the test the Lambda function before moving on. So I set up a test environment for the Lambda function with the code provided by AWS and ran the test and waited for the output, an error code in the case, to appear before I moved on to the next section. This is where I began to experience some issues, in this case, if it worked successfully I was supposed to receive a “200 status code” if it worked properly but I kept receiving a “500 error code” meaning something was wrong. After much digging, I found out I made a crucial error when setting up the DynamoDB partition key. Instead of naming it “RideId” I had accidentally named it “RidesId” and this caused me days of digging and confusion to fix such a simple issue. Now because I can’t change the partition key, I had to delete my existing DynamoDB and name it correctly. After this fix and running the test in the test environment created earlier I began receiving the correct status code and I could move on to the last section of this project, setting up the RESTful API.
Finally, the last major step to get this project to work was to get the RESTful API configured. I was so close to finishing this project and I knew it, I was so excited to finish that I ran through the sets so quickly that when I got to the last test to make sure this project worked completely, it had failed. I was so frustrated I thought I would never be able to figure out the issue because it just seemed like it was one issue after the next keeping me from completing this project. I analyzed how I had fixed my last issue and I realized I had to delete my whole DynamoDB because I had misspelled something. So I thought, let’s try that here too. I ended up deleting my whole RESTful API and started from scratch. And that’s the beautiful thing about Cloud Computing, you can delete services at will and spin up services just as quickly making the cloud extremely agile. So now onto what I actually did to set up the API. First I choose the RESTful API card in AWS and named it and choose create, very easy. Then on a little more complicated note, I needed a way to authenticate the requests for the API calls that would be generated. For this, I used Cognito User Pools which I had used earlier in this project as well and was just as easy to set up as the RESTful API was. The last step to get this API to work was to create a new resource and method and after doing this whole process over again, this is where I believe I had made a mistake the first time around. In the method request card, there is an option called “Request Validator” and I believe the first time I had that option selected as “User” or “Ride” but the option there was supposed to be “NONE”. After I finished the resource and method request and tested it one more time the application finally worked. If the application worked it would send a little unicorn head to the destination for pickup and let you know what unicorn was on its way. Below is a picture for proof that I was able to get this project working.
Some people reading this might be thinking well, what makes this application “serverless”? There is no way a database and a website can run without servers right? Well, let me explain. “Serverless” doesn’t mean that your content and your applications don’t run on physical servers, they do. But in this case, “serverless” means that I used AWS services that could build the web application with the need for me to provision and manage the servers myself. I didn’t need to set up an EC2 instance for my website to run on. To be clear I set one up in Cloud9 but that was just for running code and using a terminal. For my website and database the server CPU, storage, etc are all “managed” but the AWS services. Here is a link to AWS’s different serverless services and what makes them “serverless” (https://aws.amazon.com/serverless/).
My Final Thoughts on this project and what I believe I could have done differently Just so I know that I fully understand the scoop of this project and the AWS services I was using, following the steps provided by AWS was not enough. To truly grasp this project and the services I was using, it was time for me to ask myself a few questions. The first question was, how could I scale this solution if I needed to. To start I needed to list out all of the services that I used (CodeCommit, AWS Amplifiy, AWS Cognito, DynamoDB, AWS Lambda, and Amazon API Gateway). Let’s go through each one to find out how I can scale this solution. CodeCommit,