How I used AWS CloudWatch to monitor infrastructure performance, visualize resource usage, and configure a CPU utilization alarm for my cloud-hosted React application.

Introduction: Why Monitoring Matters

Deploying a web application to the cloud is exciting, but getting the application running is only the beginning. Once an application becomes publicly accessible, it is important to understand how the underlying infrastructure performs and how to detect problems before they affect users.

For this project, I used Amazon CloudWatch to monitor a React web application that I previously deployed on an Amazon EC2 instance running Ubuntu Linux and Docker.

My application was accessible through the public IP address:

http://44.249.176.43:3000

The goal was to monitor CPU utilization, network traffic, and instance health while creating a dashboard and an alarm that could help identify potential performance problems.

This project helped me understand how cloud monitoring supports application reliability, troubleshooting, and operational security.

My Application Environment

Before implementing monitoring, I already had a React application deployed inside a Docker container on an AWS EC2 instance.

The environment consisted of:

  • Amazon EC2: Hosted the application infrastructure.
  • Ubuntu Linux: Served as the instance operating system.
  • Docker: Containerized the React application.
  • React: Provided the web application interface.
  • Amazon CloudWatch: Collected and displayed infrastructure monitoring metrics.

Users accessed the application over the internet through port 3000.

Although the application was running, I wanted better visibility into the infrastructure supporting it.

Why I Chose Amazon CloudWatch

I selected Amazon CloudWatch because my application was already running on AWS.

CloudWatch integrates directly with Amazon EC2, making it possible to monitor infrastructure without installing and managing an entirely separate monitoring platform.

For this project, I focused on four types of metrics.

Metric What it tells me
CPUUtilization How much EC2 CPU capacity is being used
NetworkIn How much network data the instance receives
NetworkOut How much network data the instance sends
StatusCheckFailed Whether EC2 instance or system health checks have failed

These metrics provide useful information about the health and performance of the server hosting my application.

CloudWatch also supports dashboards and alarms, which make it easier to visualize performance and identify unusual conditions.

Why not Prometheus or Grafana?

Prometheus and Grafana are powerful tools, especially for environments requiring detailed application metrics and advanced visualization.

However, CloudWatch was a better fit for this project because it required less setup and integrated directly with the EC2 instance.

One limitation is that standard EC2 metrics do not automatically reveal everything happening inside Docker or React. More detailed container and application monitoring would require additional instrumentation or agents.

Step 1: Accessing EC2 Metrics in CloudWatch

The first step was to open the AWS Management Console and navigate to Amazon CloudWatch.

From there, I selected:

CloudWatch → Metrics → EC2 → Per-Instance Metrics

This section displayed monitoring information associated with my EC2 instance.

I focused on CPU utilization, incoming network traffic, outgoing network traffic, and EC2 status checks.

These metrics helped me understand how AWS collects performance information from the infrastructure hosting my Dockerized application.

[Insert screenshot: CloudWatch EC2 metrics showing CPUUtilization, NetworkIn, and NetworkOut]

Step 2: Creating a CloudWatch Dashboard

Next, I created a CloudWatch dashboard named:

StudentAppDashboard

I added widgets for CPU utilization, incoming network traffic, and outgoing network traffic.

The dashboard provided a centralized view of the EC2 instance's performance.

Instead of opening individual metric graphs every time I wanted to check the server, I could view multiple measurements in one location.

This is useful when investigating potential performance problems. For example, a sudden increase in CPU utilization could indicate heavier processing activity, while a change in network traffic could suggest increased application usage.

However, these infrastructure metrics alone cannot establish exactly how many users visited the React application or whether individual HTTP requests succeeded.

[Insert screenshot: StudentAppDashboard with CPU and network widgets]

Step 3: Configuring a High CPU Alarm

Monitoring metrics is useful, but checking a dashboard manually all day is not practical.

To address this, I configured a CloudWatch alarm named:

HighCPUAlarm

The alarm was designed to enter the alarm state when CPU utilization exceeded 80% according to its configured evaluation period.

This threshold could help identify situations where the EC2 instance is experiencing unusually high CPU demand.

For example, if the application begins receiving more traffic or another process consumes significant CPU resources, the alarm can indicate that further investigation may be needed.

CloudWatch alarms can also be connected to notification services such as Amazon SNS. An alarm does not automatically send an email unless an appropriate notification action has been configured.

[Insert screenshot: HighCPUAlarm configuration and current state]

Step 4: Verifying the Application and Monitoring

To confirm the application environment, I used the following command on the Ubuntu EC2 instance:

sudo docker ps 

This command lists running Docker containers, including information such as the container name, image, status, and exposed ports.

I also accessed the application through its public address:

http://44.249.176.43:3000

I then reviewed the CloudWatch dashboard to inspect the metrics collected for the EC2 instance.

My original project evidence included the running React application, Docker container status, EC2 monitoring metrics, the CloudWatch dashboard, and the CPU alarm configuration.

[Insert screenshot: React application running in the browser]

[Insert screenshot: Docker container status from sudo docker ps]

Together, these screenshots demonstrate the relationship between the application deployment and its underlying infrastructure monitoring.

It is important to distinguish monitoring configuration from alarm testing: creating an alarm does not necessarily prove that the threshold was triggered or that a notification was delivered.

Security Considerations

Security is an important part of cloud monitoring because the monitoring environment can expose information about infrastructure performance and system behavior.

Network security

AWS Security Groups control network traffic to the EC2 instance.

My application required access to port 3000, while SSH access used port 22.

For a production environment, SSH should be restricted to authorized sources or replaced with a more controlled management solution. Application traffic should also be protected with HTTPS.

Identity and Access Management

CloudWatch permissions are managed through AWS Identity and Access Management (IAM).

Only authorized users and services should be able to view monitoring data, create alarms, or modify dashboards.

Following the principle of least privilege reduces the risk of unauthorized changes to monitoring configurations.

Sensitive information

Passwords, API keys, authentication tokens, and other sensitive information should never be exposed in application logs, screenshots, or dashboards.

Monitoring data should be retained and accessed according to organizational security requirements.

Application Monitoring Architecture

The following diagram shows how the application and monitoring components fit together.

 Internet Users | v AWS Security Group | v Amazon EC2 Instance Ubuntu Linux | v Docker Container | v React Application Amazon EC2 Metrics | v Amazon CloudWatch / \ v v Dashboard CPU Alarm StudentAppDashboard HighCPUAlarm 

The React application runs inside Docker on EC2. CloudWatch collects EC2 infrastructure metrics independently and makes those measurements available through dashboards and alarms.

This separation is important because the dashboard measures the hosting infrastructure, not the internal performance of every React component or user interaction.

What I Learned

This project taught me that deploying an application and operating an application are two different responsibilities.

Before implementing CloudWatch, I mainly focused on whether my React application was running and accessible.

After working with CloudWatch, I began thinking more about the health of the underlying infrastructure.

Three lessons stood out.

First, visibility is essential. Without monitoring, performance issues may remain unnoticed until users report them.

Second, dashboards make troubleshooting easier. Viewing CPU and network metrics together provides useful context when investigating unusual system behavior.

Third, alarms support proactive operations. A threshold-based alarm can draw attention to a potential issue without requiring an administrator to constantly watch the dashboard.

I also learned that infrastructure monitoring has limitations. To understand application errors, response times, and container-specific resource consumption, I would need to expand the monitoring solution beyond the standard EC2 metrics.

What I Would Improve Next

If I continued developing this project, I would improve the monitoring environment in several ways.

I would configure Amazon SNS notifications so that alarm state changes could notify an administrator. I would also investigate the CloudWatch Agent and container-level monitoring to collect additional memory, disk, and Docker metrics.

Another improvement would be adding application-level health checks and request monitoring. These would help determine not only whether the EC2 instance is healthy, but also whether the React application is responding correctly.

Finally, I would consider automating the monitoring configuration using Infrastructure as Code so dashboards and alarms could be reproduced consistently.

Conclusion

Monitoring is an essential part of managing cloud applications.

Through this project, I used Amazon CloudWatch to observe the EC2 infrastructure supporting my Dockerized React application, organize important metrics into a dashboard, and configure an alarm for high CPU utilization.

The experience demonstrated how AWS monitoring tools can provide useful operational visibility without requiring a separate monitoring server.

Most importantly, I learned that keeping an application available requires more than deploying it successfully. It also requires monitoring, troubleshooting, and planning for potential failures.

References

Suggested tags: AWS, CloudWatch, Docker, React, CloudComputing