• Simple AWS
  • Posts
  • Server-Side Rendering with AWS Amplify

Server-Side Rendering with AWS Amplify

A glimpse of what Amplify can do, and an analysis on why it's a good idea to use it, and why not

Back in the Paleolithic, which for software means 30 years ago, we had HTML, CSS and JavaScript, and we wrote all the structure of the website in HTML. When we wanted to create dynamic content for our website, we added PHP or Java code in the middle of that HTML, and we would run that code on the server and it would output the HTML that we wanted to put there. That process of producing the final HTML for the website by running code is called rendering, and back then it happened Server-Side.

Then came web components and frameworks like Angular, React and Vue, and they changed the paradigm a bit. Now we didn't write plain HTML with snippets of PHP or Java, but instead we wrote JavaScript code that would then output the entire HTML code. Since it was JavaScript, we could run it on the browser, at the user's computer. That's called Client-Side Rendering.

A huge benefit of Client-Side Rendering was that we were using the user's CPU. That was awesome for our pockets, we didn't have to pay for that compute capacity. However, it meant the user had to wait however long their computer took to render that website. Mind you, it wasn't considered a big problem back then. Remember that back in those days users' expectations were pretty different: it was considered normal to wait 3 or 5 seconds for a website to load. Nowadays, more than 2 seconds seems like an eternity.

As compute capacity got cheaper, someone had the idea of bringing the rendering back to the server. The idea was to use our significantly more powerful servers to render the website much faster than what the user computer could achieve, reducing load time significantly. Sure, we were paying extra, but overall the improved user experience was worth the extra money. Cloud computing played a big part there as well: Not only was infrastructure cheaper per CPU-hour, but it also required less engineering hours to create and maintain.

We didn't bring back the old languages though! Instead, we started running that same React code in our servers, as if it were the user's browser. A big reason for this is that, while all of this back and forth was happening, frontends got increasingly more complex. That led to developers being classified as frontend or backend, and while there are full stack devs, most are just strong on one side and really weak on the other one (I'm one of those cases!). So, the folks who knew how to code UIs didn't know Java or PHP (not even backend devs like those nowadays), and the folks who did know those languages didn't know how to code UIs. The solution? Let's create a framework like Next.js that runs that same React code in our servers. That way, we get the best of both worlds: Frontend frameworks with Server-Side Rendering!

That's how we went from Server-Side Rendering, to Client-Side Rendering, and back to Server-Side Rendering. I've said it often, technology is cyclic.

How does Amplify help

AWS Amplify is a set of tools that help frontend devs use AWS infrastructure and even build backends, without knowing a lot about infrastructure or backend. There's two parts to it: Amplify Hosting is a managed service that provides hosting and CI/CD for serverless apps. Amplify Studio is a visual development environment that lets you build a UI and a backend as with a no-code tool, with reusable components. We're going to use Amplify Hosting, but you might be interested in checking out Amplify Studio.

Why AWS Amplify instead of an EC2 instance?

We know that AWS Amplify is going to be using EC2 instances behind the scenes, right? So, since we really know our way around AWS (I mean, you're reading a newsletter about AWS!), why shouldn't we just use EC2 instances for this instead of relying on a managed service? You could! It's a bit of our classic buy vs build decision, right? And you know by now that I always recommend you default to managed services and only build if there's a good reason to do so. I'm tempted to recommend the same here, but Amplify takes the managed in managed service and cranks it up to 11, and the price reflects that.

Amplify works as a self-service platform that people with little to no knowledge of cloud infrastructure can use to develop and deploy their applications. This is like an extremely managed big service: You're no longer solving just one part of the problem, but the entire problem of hosting an app in the cloud. It does get pretty expensive, so you probably want to consider EC2, or an ECS cluster on Fargate (more expensive than plain EC2, but easier). Let's run some numbers, so you can see how much it can really cost you.

AWS Amplify Pricing

Here's how Amplify charges you:

  • Build and deploy: $0.01 per minute

  • Data storage: $0.023 per GB per month

  • Data transfer out: $0.15 per GB served

  • Requests for SSR: $0.30 per 1 million requests + $0.20 per GB-hour

For example, say you're a startup with the following assumptions:

  • 10,000 daily active users

  • 5 devs, each doing 2 commits a day

  • Average build time is 3 minutes

  • The team works Monday to Friday (20 days/month) <-- this is the least realistic assumption for startups

  • The app is 25 MB

  • Average page size is 1.5 MB

Here are our calculations:

Total build time per month = devs * commits/day * days/month * avg. build time = 5 * 2 * 20 * 3 = 600 build minutes per month. 600 * $0.01 = $6

Monthly GB served = daily active users * average page size * days/month = 10,000 * (1.5/1024) * 30 = 439.45 GB. 439.45 * $0.15 = $65.92

Monthly GB storage = app size * builds/month = (25/1024)(5*2*20) = 4.88 GB. 4.88 * $0.023 = $0.11

Total charges = $6 + $65.92 + $0.11 = $72.03/month

Ok, that wasn't so bad, right? Well, it's dominated by Monthly GB served, so let's run those numbers with CloudFront:

  • For the most expensive regions: 439.45 * $0.12 = $52.73

  • For the least expensive regions: 439.45 * $0.085 = $37,35

Amplify is 25% to 75% more expensive! Is that a lot? It depends. 75% more on $0,10 is less than the electricity I spent typing this sentence (shame on me! especially for adding this parenthesis to make the sentence long enough for that claim to be true). 75% more on $1.000 is $750, I'll set up CloudFront for you for that money!

AWS Amplify for the backend

Amplify also lets you host a backend, which it runs in Lambda functions. You don't have a lot of control over it, but it works well for its intended audience: People who wouldn't know what to do if they had a lot of control over their Lambda functions. Amplify also lets you consume other AWS services easily, through declarative and easy-to-use libraries. That way, you can consume Cognito or S3 from the frontend without knowing a lot about Cognito or S3. Here's the complete list of libraries for Amplify, and you can check the Readme of the JavaScript one as an example of its features.

Scenario

You work 8 hours a day as an engineer, and you want to launch a startup in your free time. You know you want good practices, but you don't have the time to set everything up manually. You want to start with the website, built with React and Next.js. You want Server-Side Rendering, and obviously a CI/CD Pipeline. You want everything to be serverless so you pay as little as possible while you get the hang of running a startup, getting users and all of that (which is actually the most difficult part).

Solution

Host the application in AWS Amplify, which handles hosting and CI/CD. As you build the backend, either use Amplify to create your Lambda functions, or go with something more traditional like Serverless or SAM, depending on your expertise.

Step-by-step Instructions

Step 0: Setup

  1. Download and install Node.js from the official website. Alternatively, install nvm and your favorite version of Node.js

  2. Install npm if it didn't come with Node.js.

  3. Install yarn: npm install --global yarn

  4. Install git

Step 1: Create a Next.js app

  1. Open a terminal

  2. Run the following command: yarn create next-app

  3. Follow the prompts:

    What is your project named? simpleaws-app

    Would you like to use TypeScript? No

    Would you like to use ESLint? Yes

    Would you like to use Tailwind CSS? No

    Would you like to use src/ directory? Yes

    Would you like to use App Router? (recommended) Yes

    Would you like to customize the default import alias? No

  4. Change directories to the app's directory: cd simpleaws-app

  5. Start the app locally: yarn dev

  6. Open your browser, go to http://localhost:3000 and check that the page loads correctly.

Step 2: Create a git repo for the app

  1. Go to https://github.com/new and create a new repository

  2. Init the repo locally: git init

  3. Add the GitHub repository as an origin (replace YOUR_USERNAME and PROJECT_NAME with your values): git remote add origin [email protected]\:username/project-name.git

  4. Add the files, commit and push:
    git add .

    git commit -m 'initial commit'

    git push origin main

Step 3: Create an Amplify project

  1. Go to the Amplify console

  2. Scroll down to the Get started section, and under Amplify Hosting, click Get started

  3. Select GitHub and click Continue

  4. Click Authorize AWS Amplify (us-east-1) (the green button)

  5. Select your user or organization and click Continue

  6. Select Only select repositories, click the dropdown Select repositories and click on your repo. Click Install & Authorize

  7. Authenticate to GitHub with your security key, or click Use your password (it's in a really small font) and enter your password.

  8. Click the dropdown under Recently updated repositories and select your repo. Leave branch as main, and click Next

  9. Verify the Build and test settings (they should be fine, they were created by Next.js when you initialized the project)

  10. Check Allow AWS Amplify to automatically deploy all files hosted in your project root directory

  11. Click Next

  12. Click Save and deploy

  13. Wait until Provision, Build and Deploy are done

Step 4: Test the app

  1. Click on the link under the window icon with the Amazon arrow. Verify that the website loads correctly.

Step 5: Delete the app

  1. On the top right corner click Actions

  2. Click Delete app

  3. Enter "delete"

  4. Click Delete

Explanation

Step 0: Setup

Just installing some tools and dependencies.

Step 1: Create a Next.js app

Next.js has this awesome project initializer, that creates all the basic scaffolding you need. It is a bit opinionated, but I've never met anyone who doesn't like it (if you don't like it, let me know, you'll be the first!). Besides, it fits the scenario: You just want to get things done.

Step 2: Create a git repo for the app

We need the app in a git repo so Amplify can track changes to branches and pull the code from there. You can use GitHub, GitLab, Bitbucket or CodeCommit. You can also not set up a git repo and upload the code manually (or reference an S3 bucket), but in that case Amplify can't do the CI/CD for you.

Step 3: Create an Amplify project

The only odd thing here would be the build steps. Amplify auto-detects them from your package.json file, and creates the configuration file that you saw in that step. Of course, you can edit it. I'd recommend you keep it in line with your package.json file though.

Step 4: Test the app

After everything is deployed, Amplify will be serving your app in a URL that looks something like branch-name.d1m7bkiki6tdw1.amplifyapp.com. You can set up a custom domain through the Amplify console. Don't just go to Route 53 and point a domain to your Amplify URL, that'll fail because of the SSL certificates.

Step 5: Delete the app

Let's not pretend like we always remember to delete the things we deploy. This is a friendly reminder to delete the app!

Best Practices

Operational Excellence

  • Set up a branch for each environment: Create a dev env where Amplify deploys from the dev branch, and a prod env where Amplify deploys from the main branch. Only commit to those branches through pull requests. That way, merging a PR means a release in that environment.

  • Monitor Performance: Amplify has a monitoring service that allows you to view logs, build events, and other metrics.

Security

  • Use Amplify's Built-in Authentication: Amplify integrates with Cognito for user authentication. This lets you use a Cognito user pool really easily.

Reliability

  • Data Backup and Versioning: If you're using Amplify DataStore, regularly backup your data.

Performance Efficiency

  • API Caching: If you're using GraphQL with AppSync, enable caching to improve API response times and reduce the load on your backend.

Cost Optimization

  • Consider not using Amplify: I don't want to position myself for or against Amplify, because the decision depends on your scenario and your problems (remember there is no single best solution!). Just consider the costs, the tradeoffs, and analyze what's the best solution for you. It may be Amplify, it may be doing things manually! Overall, remember that the cost of maintaining software is much higher than the cost of building the initial version.

Recommended Tools and Resources

I've got two Amplify workshops for you:

Did you like this issue?

Login or Subscribe to participate in polls.

Reply

or to participate.