Deploying a Single Page Application (SPA) on AWS: A Beginner's Guide. Part 1. Theory
Tags: aws, webdev, architecture, beginners
Published: 2023-10-24 04:40:59

# Preface

In the realm of IT solutions, the age-old question of where to deploy your containers invariably leads to the ubiquitous answer, "It depends." The choice hinges on various factors such as the scale, skill set, time constraints, and budget considerations.

This article is dedicated to the specific scenario of migrating on-premises single-page applications (SPAs) to the cloud. One notable feature of this series is its commitment to technical neutrality. You have the freedom to construct your Frontend static assets with any framework of your preference or even opt for raw HTML. Likewise, you can employ any programming language to craft your Backend, provided it exposes business logic through a REST API.

# Prerequisites

To embark on this tutorial, ensure you have the following essentials at your disposal:

- AWS CLI - [AWS Command Line Interface](https://aws.amazon.com/cli/)

- Frontend - static web assets for your [SPA](https://developer.mozilla.org/en-US/docs/Glossary/SPA) - encompassing index.html, _js,_ css, and other relevant files

- Backend - a [REST](https://developer.mozilla.org/en-US/docs/Glossary/REST) API server, encapsulated within a [container](https://www.docker.com/resources/what-container/#:~:text=A%20Docker%20container%20image%20is,tools%2C%20system%20libraries%20and%20settings.)

That's all you need to get started.

# Source code repository

[javatask/aws-spa-beginners-guide: Code for the blog series on porting single page application to AWS (](https://github.com/javatask/aws-spa-beginners-guide)[github.com](http://github.com)[)](https://github.com/javatask/aws-spa-beginners-guide)

# Cloud Applications Should Be FROSST by Gregor Hohpe

In his book Gregor Hohpe [**Cloud Strategy: A Decision-based Approach to Successful Cloud Migration**](https://www.amazon.de/-/en/Gregor-Hohpe/dp/B08F6TVVTF) described the principle of making your application "cloud ready. The goal of this series is to follow it:

FROSST means Cloud Ready: **F** rugal, **R** elocatable, **O** bservable, **S** eamlessly updatable, internally **S** ecured, and failure **T** olerant.

Let's deep dive into these principles:

**F** rugal - refers to the conservative and efficient use of CPU and memory resources, avoiding unnecessary wastefulness, while also considering aspects like deployment footprint and start-up time, without resorting to premature optimization or employing unnecessarily complex or cumbersome solutions.

**R** elocatable - refers to the ability to move an application from one data center or server to another without requiring a complex migration process, allowing for scaling, quick redeployment in case of failure, updates, or use in discounted cloud instances, facilitated by methods such as externalizing state and avoiding reliance on single physical instances.

**O** bservable - refers to the ability to analyze and understand the state and performance of the system without needing to plug in a debugger, through means such as exposing endpoints that report readiness and liveness, monitoring SLA compliance, and utilizing logs and tools like distributed tracing, thereby enabling scenarios like relocatability, failure prediction, and troubleshooting in distributed systems.

**S** eamlessly updatable - the ability to deploy updates without downtime or disruption, often during regular business hours, through the use of practices like backward compatibility, feature toggles, simultaneous existence in different versions, and aided by characteristics like frugality, relocatability, observability, and external tools and automation such as green/blue deploys.

internally **S** ecured - refers to the practice of incorporating security measures within the application itself, rather than solely relying on external perimeter security, adopting a "trust no one" approach that may include authenticating API gateways and end-users, testing against common security risks, and implementing embedded authorization or authentication mechanisms, to ensure robust protection against unauthorized access and vulnerabilities, irrespective of the environment in which the application is deployed.

failure **T** olerant - refers to the ability to continue functioning in a degraded mode without complete failure, even when components or dependent services encounter problems, by accepting and managing failures internally without propagating them to the end user, and having mechanisms to recover automatically, a characteristic supported by frugality, relocatability, and observability, and requiring a conscious design decision.

# Use Case

The SPA embodies a classic three-layered architecture (Figure 1). For practical application, we will employ a combination of HTML files for Frontend and opt for the [Spring Boot Tutorial Rest API app](https://github.com/spring-guides/gs-rest-service/tree/main/complete) as our Backend. You can access all the code increments in my [Git repository](https://github.com/javatask/aws-spa-beginners-guide) - [javatask/aws-spa-beginners-guide: Code for the blog series on porting single page application to AWS (](https://github.com/javatask/aws-spa-beginners-guide)[github.com](http://github.com)[)](https://github.com/javatask/aws-spa-beginners-guide).

![](https://upload.wikimedia.org/wikipedia/commons/1/1b/Single_Page_Applications_structure.png?20130627120913)

Figure 1. Single-page application [(Link to Wikipedia)](https://upload.wikimedia.org/wikipedia/commons/1/1b/Single_Page_Applications_structure.png)

The application migration process unfolds in the following steps:

1. Host your static assets using CloudFront and S3 services. The primary objective at this juncture is to have your Frontend up and running on a publicly accessible https URL.

2. Proceed to obtain an independent URL for your Backend and perform testing.

3. Subsequently, link your Backend URL to the `/api` path on the primary Frontend URL to facilitate [AJAX](https://developer.mozilla.org/en-US/docs/Web/Guide/AJAX) calls.

4. The final step involves the addition of Sign-In functionality and the fortification of your Backend URL with the JWT Authorization header. This ensures that the Backend API rejects all requests devoid of a valid JWT.

Refer to Figure 2 and Figure 3 for a comprehensive depiction of the entire architecture and the interplay of its components.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1690450254336/a3122293-49ac-4088-881a-3c4f703a98cd.png)

Figure 2. Generic Architecture for Deploying Our SPA on AWS

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1690450390933/1f1e9e26-b5c2-4470-93d6-95d9d5e97bd7.png)

Figure 3. Sequence Diagram Illustrating Interactions Among the Moving Parts

Description of the Sequence diagram:

1. The user initiates a webpage request, which CloudFront fulfills by fetching static files from the S3 bucket.

2. When the user generates an API request, CloudFront forwards it to the API Gateway.

3. The API Gateway, in turn, validates the request's authenticity with Cognito.

4. If the authentication process proves successful, the Backend proceeds to handle the request, potentially fetching or storing data from the Database. The processed data is subsequently relayed to the user via the API Gateway and CloudFront.

5. In the event of authentication failure, the user receives an error message.

# In Summation

This section delineates various approaches for migrating a Single Page Application to the Cloud. It also outlines the prerequisites necessary to embark on the tutorial and delves into the use case, along with five possible architectural variations for hosting your Backend.

Stay tuned for the next instalment - "Securing Static Hosting."