Tech Blog
  • HOME
  • Blog
  • Building a serverless web app with AWS

Building a serverless web app with AWS

Published: 2025.10.28 Last updated: 2025.10.28

Star

Hello, this is Star.
I work in the development department and deal with internal systems and AWS.

Have you ever been interested in the "Serverless" concept?
I did. When I went to the AWS Summit, everyone was using serverless. I really admired this approach.

If you operate a server or infrastructure, you've probably dreamed of serverless at least once.
Everyone is using serverless, which means everyone is realizing this dream. Amazing.
Serverless web apps allow you to build applications without managing or operating servers. By leveraging AWS fully managed services, the cloud provider manages the servers and infrastructure for you.
If that were the case, we designers would be able to focus on developing the features themselves.
I still have a dream.

At that time, I needed a web app with a login function, so I created one. Since I had the chance, I decided to use it as a learning opportunity and create a serverless configuration. I want to make my dream come true too!
This was my first attempt at implementing it, so I had to research as I went, but I managed to get it to work, so I'm going to share it on my blog.
It might be good to have tech blog content that isn't audio-related every once in a while.

The flow of this article

It's something like that. Thank you in advance.

About the configuration

Architecture diagram

Here's a diagram of the architecture I created.

Let me talk about the app first.

Actually, I've been in charge of infrastructure on AWS since I entered the IT industry, and I had almost no knowledge of the app side of things. I have some experience writing small scripts and calculation code, but I've never developed a graphical user interface (GUI) application. I started from scratch.
I started by researching which framework would be best.

I think the most popular frameworks for single-page applications (SPAs) like this one are React and Vue.
Here are my thoughts after briefly trying both:

ConditionReactVue
MainstreamVery mainstreamQuite mainstream
Initial setupThere are many initial setup patternsVite + Vue seems to be almost fixed
Learning curveThere is a lot of information on the internetIt was good because it looked like an extension of HTML.
Suitable scaleLarger scale seems more suitableSmall to medium-scale projects are likely to be suitable.
FlexibilitySeems highIt seems possible

The javascript framework I chose this time is Vue.
The requirements for this app are simply to retrieve logged-in user data from DynamoDB and display it on the screen. Since the implementation is expected to be fairly simple, I didn't think it needed the flexibility of React.
Also, as I continued to learn, I found Vue to be easier to get started with than React. Since I was starting from scratch, I chose the one that seemed easier.

However, the more information I gathered, the more popular React seemed to be. It also seemed easier to support native apps with React, and React would likely win in terms of scalability.
I would like to learn React in the future.

Also, since the main focus of this article is serverless configuration, I won't go into much more detail about the app itself. To put it simply, I submitted the app requirements to Large Language Model (LLM), and they returned the source code, so I used that.
We have an in-house GPT at our company. It has security measures in place, so you can use it with peace of mind. This in-house GPT can also be used as a development companion and answers questions about office rules. It's a good guy.

Key Design Choices

Serverless configuration

Anyway, I wanted to create a serverless configuration, so I did it.

Actually, I've been in charge of infrastructure on AWS since I entered the IT industry, and I had almost no knowledge of the app side of things. I have some experience writing small scripts and calculation code, but I've never developed a graphical user interface (GUI) application. I started from scratch.

By the way, even though I'm in charge of infrastructure on AWS, I've never worked with serverless architecture. In this diagram, I've never worked with API Gateway, DynamoDB, or Cognito. I started from scratch here too. Wow.

Location of API Gateway

The difference from the general configuration is that there is an API Gateway under CloudFront.
A common configuration is to hit the API Gateway URL directly from the browser, but this time it is routed via CloudFront.
Having API Gateway and the application source S3 under CloudFront means that the API and the web application are in the same domain. I thought this would solve several problems and pitfalls at once, so I chose this configuration.

  • CORS

I think this is the most common problem I encounter when building web applications. I often see CORS errors just by interacting with S3 and CloudFront.
By placing API Gateway under CloudFront, access to the API is no longer cross-origin, allowing you to configure CORS securely.

  • SameSite cookie flag

Cognito's managed login page stores the authentication token in a cookie. To make this cookie more secure, specify the SameSite flag.
In this case, placing API Gateway under CloudFront will make it the same domain, so you can specify a value other than None for the SameSite flag. As for cookies, I wanted to make them as secure as possible, so I also added the HttpOnly and Secure flag.

This may be an unusual configuration, but I thought it would be easier to place API Gateway under CloudFront. Domain management would also only need to be done through CloudFront.

【Reference】https://dev.classmethod.jp/articles/access-api-gateway-via-cloudfront/

About Cognito Managed Login

I was so happy when this feature was released.
Before this feature was introduced, the login screen provided by Cognito was difficult to release in a production environment because the design could hardly be changed.
Suddenly, this had a modern design and could be customized to a certain extent. I was so happy. Yay! I don't need to implement a login function!

However, we encountered requirements that the managed login function could not address, such as "I want to jump to another page from the login screen" and "I want to enter specific characters here."
In the end, I decided to create the login function myself. I guess there's no such thing as a free lunch.

I think the managed login feature is very effective for personal use, Proof of Concept (PoC), etc. In this case, I thought I could go all the way to production with managed login, so I ended up with a disappointment: "I can't use managed login!"
This was a very educational experience for me, as I would not have been able to reach this conclusion until I tried it out.

About Cognito@Edge

This system uses Lambda@Edge as a CloudFront behavior to check whether access is properly authenticated.
As I will explain later, I am setting up a modified version of "Cognito@Edge" made by AWS Labs.

https://github.com/awslabs/cognito-at-edge

Here are some points to keep in mind when using Cognito@Edge, whether you are using the managed login feature or a custom login screen.
As of June 27, 2025, it seems that managed login is not supported. Therefore, you will need to edit it a bit.

On Github cognito-at-edge/src/index.ts on line 541 of

const userPoolUrl = `https://${this._userPoolDomain}/authorize?redirect_uri=${oauthRedirectUri}&response_type=code&client_id=${this._userPoolAppId}&state=${state}`;

The above part seems to be the URL of the login screen.
This URL is for the Classic Hosted UI and not the Managed Login URL.

I corrected it like this:

// ホストされたUI(クラシック)のURLをコメントアウトする
//const userPoolUrl = `https://${this._userPoolDomain}/authorize?redirect_uri=${oauthRedirectUri}&response_type=code&client_id=${this._userPoolAppId}&state=${state}`;

// マネージドログインのURLを指定する場合(作業当時はこの形式でした)
const userPoolUrl = `https://${this._userPoolDomain}/oauth2/authorize?lang=ja&response_type=code&client_id=${this._userPoolAppId}&redirect_uri=${oauthRedirectUri}&state=${state}`;

// 自作のログインURLを指定する場合
const userPoolUrl = `https://hogehoge.amivoice.com/login/`

Hope this helps.

Estimated costs

Let me try to estimate the costs first.
Because the scope of access is limited, I expect that for the time being, there will be around 50 people accessing the site per month.

For simplification purposes, Mend the free tier will be described as "within the free tier limits." Will it be less expensive? It would be desirable for the cost to be lower than the server running costs.

Jump to the summary of the estimated results!

CloudFront

  • Data transfer out to the Internet (first 1,024 GB/month free)
    • Within the free limit
  • Data transfer (outbound) to the origin (e.g., POST or PUT requests)
    • 0.01 GB/month × 0.06 USD ≒ 0.00 USD
  • Number of Requests (HTTPS) (First 1000 million requests/month are free)
    • Within the free limit

Sum: 0.00 USD *Very small amount

API Gateway

It uses the REST API.
The free quota for API Gateway is 12 months from the date of signing up for AWS. However, since the account deployed this time is already more than 12 months old, there is no free quota.

  • Request
    • 4000 times per month × 0.00000425 USD = 0.02 USD

Sum: 0.02 USD

Lambda

For API
  • Requests (1,000,000 free requests per month)
    • Within the free limit
  • Compute Hours (400,000 GB-seconds free tier)
    • Within the free limit

Sum: Free

For Lambda@Edge
  • Number of requests
    • 100 requests per month × $0.0000006 = $0.00 (monthly charge)
      • Lambda@Edge is called every time a page is accessed, but since this is an app with only two pages,
        This is calculated as 50 people × 2 pages.
  • Compute Time
    • 0.125 GB memory × 100 requests × 0.1 seconds each × $0.0000006 = $0.00 (monthly charge)

Sum: 0.00 USD *Very small amount

By the way, in the case of Lambda@Edge, which has 128MB of memory and takes 0.1 seconds to execute, if you receive 10000 requests per month, the cost will be 0.02 USD. That's cheap.

Cognito

  • Monthly active users (free up to 10,000 monthly active users)
    • Within the free limit

Sum: Free

DynamoDB

  • Data storage (up to 25GB per month free)
    • Within the free limit
  • WCU (Write Capacity Unit)
    • 100 requests/month × 0.000000715 USD ≒ 0.00 USD Write request cost *Very small amount
  • RCU (Read Capacity Unit)
    • 7500 requests/month × 0.5 read request units for eventually consistent reads × $0.0000001425 ≈ $0.00 (read request cost)

Sum: 0.00 USD *Very small amount

S3

  • Storage capacity
    • 2 MB (application storage, 0.0015974 GB) × $0.025 ≈ $0.00

Sum: 0.00 USD *Very small amount

Estimated total cost

ServiceEstimated costs
CloudFront0.00 USD*Very small amount
API Gateway0.02 USD
LambdaFree
Lambda@Edge0.00 USD *Very small amount
CognitoFree
DynamoDB0.00 USD *Very small amount
S30.00 USD *Very small amount
Total0.02 USD

0.02 USD per month + α. 1 USD is converted to 150 yen, ¥ 3 / month.

Eh, really?
I'm doing my own rough calculations, but it seems too low. I'm starting to worry if it's accurate. I used the "AWS Pricing Calculator" to estimate. Since it's an official tool, I want to believe it's accurate...

https://calculator.aws/

I thought DynamoDB would be a little more expensive. Thanks to this, the database is almost free. I would be happy if RDS and Aurora were this cheap as well.
To be honest, I don't think the table design was done well, and the queries are not optimal, resulting in a lot of requests. NoSQL is difficult.

Another big factor is that Lambda, the API backend, is included in the free tier. I think this free tier is generous. Actually, not just Lambda, AWS's free tier is generous overall. Cognito's free tier is also amazing.

If this calculation is correct, it seems like it would be okay even if the number of users increased. Given the purpose of this web app, it's unlikely that the number of users will increase that much, but even if it increased tenfold, I don't think the costs would increase that much.

Comparison with legacy configuration

Let's compare this with the legacy configuration. Let's prepare a web server, a database server, and a load balancer.
I'm aiming for the minimum configuration. Something like this?

  • Web Server
    • EC2: t3a.small
    • EBS: 10 GB
  • DB Server
    • Aurora Serverless v2 PostgreSQL compatible
      • ACU: 0.5
      • Storage:25 GB
  • ALB
    • To simplify the calculation, only fixed costs are calculated.

ServiceLegacy Configuration Estimated costsEstimated cost of this system
EC2 + EBS$ 18.85
Aurora58.38 USD
ALB17.74 USD
Total94.97 USD0.02 USD

In total monthly cost is 94.97 USD. About 14,246 yen.
This is over 4,748 times more expensive than the serverless configuration.

This is the result just for server costs. Furthermore, in terms of availability and operational costs, serverless architecture will likely win. There are only good things about it.

...I'm quite confused by the results of the calculations, which are too convenient. There may be some pitfalls.

Actual Cost

I'll look at the costs after I've been running it for a while.
When I check the costs by resource in Cost Explorer, I can only go back 14 days. Because the AWS account where this web app is deployed also runs other systems, I cannot derive the cost of this web app by looking at the costs by service.
The only way to find out is by resource, so I'll look at the costs for the past 10 days and multiply that by 3 to get the monthly cost.

*When I asked within the company later, I found out that tags had been prepared for expense management.

The results are here↓.

The costs were calculated by resource, but were re-grouped by service to create the table. Costs have been rounded.

ServiceCostEstimated costs
CloudFront0.000 USD or less0.00 USD*Very small amount
API Gateway0.003 USD0.02 USD
Lambda0.001 USDFree
Lambda@Edge0.001 USD0.00 USD *Very small amount
Cognito0.000 USDFree
DynamoDB0.000 USD or less0.00 USD *Very small amount
S30.001 USD0.00 USD *Very small amount
Total0.01 USD0.02 USD

It ended up costing about half of what I had estimated.
Judging from the cost of the API Gateway, it seems that the access was low at that time. So it's not a good sample...

One thing to note is that there was a cost for Lambda. I don't think it's above the free tier, so I seem to be overlooking where the cost is. I'll check that later.

As I was writing this, I learned that there will be an event in October or November 2025 that will increase access to this web application. The good thing about cloud and serverless is that you don't have to panic when traffic spikes like this occur.
When you think about it, this cost data also clearly shows the advantage of serverless, which is that it is cheap when not in use.

Problems that come to mind

Learning costs and awareness

Serverless architecture is a configuration in which the majority of the system is left to AWS managed services, which is probably why many people feel hesitant about it.
"Using something you don't know what it's like" can create uncertainty for engineering teams. In fact, this time too, I didn't use Amplify because "I don't want to use something I don't know what it's like." I was scared...

To implement a serverless architecture, you need to understand AWS services well enough to use managed services with confidence. Furthermore, the app side is limited to SPA-compatible JavaScript frameworks like React and Vue. A loosely coupled architecture design with proper separation between the front end and back end is required. Server-side rendering (SSR) languages ​​cannot be used (although it may be possible to do so by messing around with Lambda).

In other words, both the application and infrastructure sides need to be determined to adopt a serverless architecture. So, if you ask whether the infrastructure side can steer the mindset of all the members... I think this is more difficult in most projects.

Also, going back to the topic of learning costs, DynamoDB is difficult to use.
I think it was the right decision to adopt this method from a cost perspective.
However, by adopting this system, it is no longer something that "anyone can easily maintain and operate."

  • People who know SQL
  • Anyone familiar with the DynamoDB API

When comparing the two, the former is inevitably more popular and has a lower hurdle.

Fully managed service does not mean no management

At the beginning, I wrote that "the cloud provider manages the servers and infrastructure for you." In a serverless architecture, by moving towards fully managed services, the cloud takes over infrastructure management. This is a common explanation, and I think this is what many people think. In fact, AWS manages a lot of things for you.

However, what I felt after trying it out this time was that "not directly managing the server" and "not having to manage it" are completely different things.
While Lambda, API Gateway, DynamoDB, and other services are fully managed, and AWS handles the infrastructure aspects such as scaling and availability, you still need to manage the configuration, monitoring, security design, and cost management of each service.

Although this frees us from the traditional "server setup and maintenance" work that used to be part of application development. However, a new type of operational task emerges instead: figuring out "how to connect AWS services with each other safely and efficiently."
In other words, rather than simply “being liberated from server operations and able to focus on feature development,” I felt that this architecture requires you to focus on "how to manage each AWS service to realize the desired functionality." Serverless isn’t a mechanism that hides servers; It's a mindset of understanding cloud services, managing them properly, and leveraging them effectively.

Final thoughts

Frankly speaking, not many people in my group are interested in serverless architecture at the moment, because the task of speech recognition and serverless architecture do not go very well together.
Still, I think it would be great if we could make the web page portion serverless, as we did in this case, or automate operational tasks using AWS services, thereby improving the efficiency of tasks such as development, operation, and maintenance, and reducing running costs.
When it comes to delivering voice recognition technology to customers, this mission cannot be ignored.

If

  • you like making existing systems serverless
  • you want to operate efficiently
  • you love automation
  • you like AWS and Azure.

If you are someone like this, I would be delighted if you would consider working at Advanced Media. I look forward to hearing from you.

That's all for this article. Thank you for reading this far.
Other tech blogs are also interesting. Please take a look at the archives if you'd like.

Person who wrote this article

  • Star

    Job-hopping. Often works with AWS.
    Activities are diverse, including playing games, reading books (both novels and manga), and watching anime.
    For some reason, I once played a crane game before meeting someone and ended up with a huge stuffed animal.

     
Use API for Free