Discover Nonsense at Daily Nonsensia

This is my little corner where I share whatever I learn in the most random and honest way possible. It’s basically daily nonsense: thoughts, lessons, mistakes, and small discoveries from a beginner like me. No fancy words, no pressure just real stuff. Feel free to explore, laugh along, and drop a comment anytime. We’re all figuring it out together!

Modern library interior showcasing elegant architecture and natural light

Latest Chapters

Design process

Basic Introduction to Amazon ECS (Elastic Container Service)

Amazon ECS is a fully managed container orchestration service that enables you to run Docker-based applications at scale. It supports multiple launch types, including AWS Fargate — which abstracts away the underlying EC2 infrastructure so you don't have to manage or provision servers yourself.

Core Components of ECS

Cluster

A cluster is the main logical environment managed by AWS that contains all your services, tasks, and capacity providers.

Capacity Providers

Capacity providers define the infrastructure where your containers run. ECS supports:

  • EC2 — You manage the virtual machines.
  • Fargate — Serverless container hosting managed entirely by AWS.

Task Definition

A task definition is like a blueprint for your application. It defines:

  • Docker image
  • CPU and memory requirements
  • Networking
  • Environment variables
  • Ports and container configurations

Container Image

Your application is packaged into a Docker image and pushed to a container registry such as:

  • Amazon Elastic Container Registry (ECR)
  • Docker Hub

Task

A task is a running instance of a task definition. It represents one or more running containers.

Service

A service ensures that a specified number of task instances are always running. It also supports:

  • Automatic recovery of failed tasks
  • Load balancing
  • Scaling across multiple instances

Typical ECS Workflow

does:

  1. Build your application into a Docker image.
  2. Push the image to ECR or Docker Hub.
  3. Create a Task Definition using that image.
  4. Run Tasks or create a Service in an ECS Cluster.
  5. ECS manages deployment, scaling, and availability automatically.

Simple Real-World Analogy

to owning a food delivery business:

  • Docker Container = a packed lunch box with everything needed for one meal.
  • Task Definition = the recipe/instructions for making the lunch box.
  • Task = one prepared lunch box being delivered.
  • Cluster = the kitchen area.
  • EC2/Fargate = the workers or kitchen machines doing the cooking.
  • Service = the manager making sure enough lunch boxes are always available.

References

  1. Introduction to Amazon Elastic Container Service (ECS)

  2. ECS vs EKS Comparison

Read more
Design process

Internet Gateway vs Private Gateway in AWS

Internet Gateway vs Private Gateway in AWS

When working with AWS networking, understanding how your VPC communicates with the outside world is essential.


Internet Gateway (IGW)

  • Enables public internet traffic to reach resources in a VPC
  • Acts as the connection between a VPC and the internet
  • Required if resources (like web servers) need public access
  • Without an Internet Gateway, resources inside the VPC cannot be accessed from the internet

Private Gateway (Virtual Private Gateway – VGW)

  • Enables secure communication through a VPN tunnel
  • Allows on-premises infrastructure to connect privately to your VPC
  • Uses encryption to protect data traveling over the internet
  • Commonly used for hybrid cloud architectures

Key Concepts

  • VPC (Virtual Private Cloud):
    An isolated section of the AWS cloud where you launch resources

  • VPN (Virtual Private Network):
    A secure, encrypted tunnel used to connect networks over the internet


In Simple Terms

  • IGW → like a public playground, anyone can come and play.
  • VGW → like a school playground, only authorized students are allowed

Understanding these components is fundamental when designing secure and scalable AWS architectures.

Don’t worry — these concepts are simple once you think of them in terms of “public vs private access.”

Read more
Design process

AWS Lambda Logging Best Practices: A Complete Guide for Reliable Serverless Applications

Introduction

AWS Lambda is a serverless compute service that frees you from managing servers, scaling, or infrastructure. However, this also means you lose direct access to traditional debugging tools like SSH or local log files. Effective logging becomes your primary window into your application's behavior.

Good logging helps you debug issues, monitor performance, detect security problems, optimize costs, and maintain compliance. Lambda automatically streams logs to Amazon CloudWatch, but without a solid strategy, logs can become noisy, expensive, or hard to use.

This guide covers how Lambda logging works and the critical best practices to make it efficient, searchable, and cost-effective.

How AWS Lambda Logging Works

Lambda automatically captures and sends these logs to CloudWatch Logs for every invocation:

  • INIT_START, START, END, and REPORT lines — These include runtime details, request ID, duration, billed duration, memory usage, and initialization time.
  • Custom logs — Anything you output via console.log(), print(), or standard output/error streams.

You can add your own logs to track application flow, variables, errors, or business events. Errors (exceptions, timeouts, memory issues) are also captured automatically.

Tip: Use JSON.stringify() (with care) to log objects structuredly, and consider redacting sensitive data (e.g., passwords, personal info) using a replacer function.

Best Practices for Lambda Logging

1. Provide Enough Context (But Not Too Much)

Every log should be actionable. Include:

  • Relevant event details or inputs (summarized).
  • Application state or key variables.
  • Environment variables or configuration settings (e.g., stage, version).
  • Timestamps (often added automatically) and outcomes.

Avoid logging entire large payloads (e.g., full HTTP requests or Kinesis records) in production, as this drives up costs quickly.

2. Use a Proper Logging Framework

Relying only on console.log() works for simple cases but lacks structure. Use established libraries:

  • Node.js: Winston, Pino (fast and lightweight).
  • Python: Built-in logging module.
  • Java: Apache Log4j.

These frameworks support log levels, structured output, metadata, and asynchronous logging—ideal for serverless. Consider packaging them via Lambda Layers for reuse.

3. Apply Appropriate Log Levels

Categorize logs to control verbosity:

  • DEBUG — Detailed tracing (development only).
  • INFO — Normal operational events.
  • WARN — Potential issues.
  • ERROR — Failures that need attention.
  • CRITICAL — Severe problems.

Set the log level via an environment variable (e.g., LOG_LEVEL=info in production). This lets you increase verbosity temporarily during incidents without redeploying.

4. Use Correlation IDs (Request IDs)

Assign a unique ID to each request. Lambda provides context.awsRequestId automatically.

  • Log this ID with every message.
  • It allows you to trace a single invocation across multiple log lines or even chained Lambda functions and services.

This is essential for distributed systems debugging.

5. Log in Structured JSON Format

JSON logs unlock powerful querying in CloudWatch Logs Insights. You can filter by fields, run aggregations, and create dashboards easily.

Example structure:

{
  "level": "info",
  "message": "User processed successfully",
  "requestId": "abc-123",
  "userId": "user456",
  "durationMs": 245
}

This beats plain text for searchability and analysis.

6. Don’t Log Too Much – Mind the Costs

CloudWatch pricing includes ingestion ($0.50/GB) and storage. Built-in Lambda logs (START/END/REPORT) add overhead for every invocation. Excessive logging of payloads can lead to surprisingly high bills.

Best practices:

  • Use log levels to reduce production volume.
  • Summarize or sample high-volume data.
  • Avoid logging in hot paths unless necessary.

7. Configure Log Retention and Rotation

CloudWatch retains logs indefinitely by default. Set a realistic retention policy (e.g., 30 or 90 days) in your IaC (Terraform, Serverless Framework, etc.).

Benefits:

  • Reduces storage costs ($0.03/GB/month, compressed).
  • Limits exposure of old sensitive data.
  • Keeps log groups performant.

Regularly review and archive older logs if needed for compliance.

8. Centralize, Monitor, and Alert

  • Centralize: Use CloudWatch as the hub. Forward to tools like Elasticsearch, Datadog, or Lumigo for advanced analysis if your setup grows.
  • Monitor & Alert: Create CloudWatch Metrics Filters and Alarms for patterns like high error rates, specific error messages, or latency spikes. Route notifications via SNS, email, or PagerDuty.

Common Pitfalls to Avoid

  • Logging sensitive data.
  • Using plain strings instead of structured logs.
  • Noisy DEBUG logs left enabled in production.
  • Ignoring costs until the bill arrives.
  • Poor or missing request ID correlation.

Conclusion

Strong logging turns AWS Lambda from a black box into an observable, maintainable system. By providing context, using frameworks and levels, structuring logs as JSON, tracking requests with correlation IDs, and managing retention/costs, you’ll debug faster, reduce expenses, and build more reliable serverless applications.

Start small: Audit your current functions for log levels and JSON structure, then add retention policies. Over time, these practices will pay dividends in operational efficiency.

Further Reading:

What logging challenges have you faced with Lambda? Share in the comments!

Read more
Design process

ECS Auto Scaling: How It Works and Why It Matters

Amazon Elastic Container Service (ECS) is one of AWS’s most powerful tools for running containerized applications. One of its biggest advantages is built-in auto-scaling, which automatically adjusts resources based on real demand. This helps maintain application performance during traffic spikes while keeping costs under control by scaling down when demand drops.

ECS handles auto-scaling at two distinct levels:

  1. Task-level Scaling (Service Auto Scaling) — available for both EC2 and Fargate launch types.
  2. Infrastructure-level Scaling (Cluster Auto Scaling) — available only for the EC2 launch type.

Understanding the ECS Hierarchy

Before diving into scaling, it’s important to understand how ECS is structured:

  • An ECS Cluster contains one or more ECS Services.
  • An ECS Service runs and maintains one or more ECS Tasks.
  • Each Task contains one or more containers that make up your application.

Scaling at the service level changes the number of tasks running. Scaling at the cluster level changes the underlying compute capacity.


1. Task-Level Scaling (Service Auto Scaling)

This is the most commonly used form of auto-scaling in ECS and works with both EC2 and Fargate.

You define scaling policies for your ECS Service so it automatically adds or removes tasks based on metrics such as:

  • CPU utilization
  • Memory utilization
  • Custom metrics (via CloudWatch)
  • Request count (when used with a load balancer)

Example policy: “If average CPU utilization across all tasks exceeds 75% for 5 minutes, add 2 tasks. If it drops below 40%, remove 1 task.”

Benefits:

  • Handles traffic spikes gracefully.
  • Simple to configure through the AWS Console, CLI, or CDK/Terraform.
  • Works seamlessly with Application Load Balancers for even traffic distribution.

Service Auto Scaling only manages the number of tasks. It does not automatically provision more servers (EC2 instances).


2. Infrastructure-Level Scaling (Cluster Auto Scaling)

If you’re using the EC2 launch type, you also need to scale the underlying virtual machines. This is where Cluster Auto Scaling (also called managed scaling with Capacity Providers) comes in.

Key Concept: EC2 Auto Scaling Groups + ECS Capacity Providers

When you enable managed scaling on a Capacity Provider linked to an Auto Scaling Group, ECS automatically:

  • Monitors the resource needs of your tasks.
  • Creates custom CloudWatch metrics and alarms.
  • Manages a target tracking scaling policy.
  • Adds or removes EC2 instances as needed.

Important behaviors:

  • When scaling out from zero instances, ECS launches 2 instances by default.
  • ECS uses the AWSServiceRoleForECS service-linked IAM role to manage scaling.
  • You set a target capacity percentage (e.g., keep instances at 70% utilization).
  • Never manually change the desired capacity if ECS is managing it — let ECS control the scaling policy.

Note: This does not apply to Fargate. With Fargate, AWS manages all the underlying infrastructure, so you only need Service Auto Scaling.


EC2 vs Fargate: Why It Matters for Scaling

FeatureEC2 Launch TypeFargate Launch Type
Task ScalingYesYes
Infrastructure ScalingYes (Cluster Auto Scaling)No (AWS-managed)
Management OverheadHigher (manage instances)Lower
Cost ModelPay for EC2 instancesPay per vCPU/memory per second
Best ForFull control, custom AMIs, cost optimizationSimplicity and reduced ops

How Service Auto Scaling and Cluster Auto Scaling Work Together

These two scaling mechanisms are independent:

  • You can scale tasks without scaling instances (risky on EC2 — tasks may go pending).
  • You can scale instances without scaling tasks.
  • For optimal performance on EC2, you should use both.

Best Practice: Use Service Auto Scaling + Cluster Auto Scaling with Capacity Providers. This creates a complete auto-scaling loop where tasks and infrastructure scale in harmony.


Conclusion

ECS Auto Scaling is a game-changer for running production workloads efficiently. By combining Service Auto Scaling (task level) with Cluster Auto Scaling (infrastructure level on EC2), you can build highly responsive, cost-optimized container environments that handle unpredictable traffic with minimal manual intervention.

Whether you choose Fargate for simplicity or EC2 for maximum control, understanding these two scaling layers is essential for mastering AWS container orchestration.

Happy scaling!


References:

  • AWS Documentation: Cluster Auto Scaling
  • GeeksforGeeks: Introduction to Amazon ECS
  • Judoscale Blog: ECS Autoscaling

Read more
Design process

Simplifying User Authentication with Amazon Cognito

When building projects, we often feel lazy about handling access control. Who can do what? How do we authorize users? AWS solved this headache with a service called Amazon Cognito.

Cognito is a fully managed service that helps you handle:

  • User authentication (sign-up, sign-in, password reset)
  • Multi-factor authentication (MFA)
  • Synchronization of user data across devices
  • Integration with social identity providers like Facebook, Google, and Amazon, so users can log in with existing accounts

Amazon Cognito Architecture

Amazon Cognito has several key components:

  1. User Pools

    • Acts as your user directory
    • Manages authentication: email/password, phone number, or social logins
    • Handles account info, multi-factor authentication, and password resets
  2. Identity Pools

    • Provides temporary AWS credentials to access AWS resources (like S3 or DynamoDB)
    • Can accept identities from:
      • User Pools
      • Social logins (Google, Facebook, Apple)
      • SAML or OpenID Connect
      • Anonymous guest access
  3. Cognito Sync

    • Synchronizes user data across devices
    • Uses S3 as backend storage
  4. Cognito Streams

    • Provides real-time updates on user data changes

More about Cognito on GeeksforGeeks


User Pools vs Identity Pools — What’s the Difference?

Here’s an easy way to remember:

FeatureUser PoolIdentity Pool
PurposeAuthentication (who you are)Authorization (what you can access)
HandlesSign-up, sign-in, MFA, password resetTemporary AWS credentials
TokensJWT tokens (ID, access, refresh)AWS credentials
Use caseManage users directlyLet users access AWS resources

When to use both:
If you want authenticated users (User Pool) to access AWS resources securely (Identity Pool), use both together.

Flow:

  1. User signs in via User Pool → receives JWT tokens
  2. Tokens are sent to Identity Pool → exchanged for temporary AWS credentials
  3. User accesses AWS resources using those credentials

When you don’t need both:

  • Only User Pool → if you just need user authentication, not AWS access
  • Only Identity Pool → if you just need social or guest access to AWS resources

Step-by-Step: Connecting User Pools and Identity Pools

Think of it as “how to connect your login system to AWS resources.”

1. Set up a User Pool

  • Go to AWS Management Console → Cognito → User Pools → Create a user pool
  • After creating it, note down:
    • User Pool ID → unique pool identifier
    • App Client ID → key for your app to use the pool

2. Set up an Identity Pool

  • Go to AWS Management Console → Cognito → Identity Pools → Create a new identity pool

3. Link User Pool to Identity Pool

  • Open your Identity Pool → User access tab → Add identity provider
  • Select Cognito User Pool and enter:
    • User Pool ID
    • App Client ID

4. Set up roles for users

  • AWS roles define what users can do
  • Options:
    • Default role → everyone gets the same permissions
    • Role with rules → assign roles based on attributes (group, email, etc.)
    • Preferred role → users can request a specific role if allowed

5. Map user attributes to principal tags (optional)

  • Tags are extra info attached to AWS credentials
  • Options:
    • Inactive → no tags
    • Default mappings → AWS uses sub (user ID) and aud (app ID)
    • Custom mappings → pick which user attributes become tags

6. Save changes

  • Click Save after configuring everything

Summary:

  • User Pool → handles login/authentication
  • Identity Pool → handles access to AWS resources
  • Linking → tells AWS which users can access which roles
  • Roles & tags → control what users can do

Official AWS guide


Read more
Design process

Why React Hooks Do Not Work Inside Async Functions

While developing a new project using Next.js, I encountered an issue where React Hooks could not be used inside an asynchronous function. After researching this problem, I found that it is related to the Rules of Hooks defined by React.


React Rules of Hooks

According to the official React documentation, hooks must always be called in the same order during every render.

React depends on this consistent order to correctly associate state and effects with each hook call.

If the order changes between renders, React may lose track of which state belongs to which hook, leading to errors such as:

  • "Rendered fewer hooks than expected"
  • "Rendered more hooks than expected"
  • State mismatches

Common Violations of the Rules of Hooks

Some common patterns that violate these rules include:

  • Calling hooks inside conditions (if, else, ternary operators)
  • Calling hooks inside loops (for, while)
  • Calling hooks after early returns
  • Calling hooks inside callbacks or event handlers
  • Calling hooks inside async functions
  • Calling hooks inside class methods
  • Calling hooks at the module level

Hooks Inside Async Functions

One common mistake is attempting to use hooks inside an async function.

Hooks must run during the rendering of a React function component. React relies on the order of hooks during this render process to manage state and effects correctly.

If hooks are called inside an async function, they are executed outside the component’s render flow, which breaks React’s hook tracking mechanism.

Because of this, hooks can only be called inside:

  • React function components
  • Custom hooks

Not inside regular JavaScript functions such as async functions.


Solution: Using Async Logic Inside useEffect

A common solution is to keep the useEffect callback synchronous while calling an internal async function.

Example

import { useEffect, useState } from "react";

export default function Example() {
  const [data, setData] = useState(null);

  useEffect(() => {
    async function fetchData() {
      const res = await fetch("/api/data");
      const json = await res.json();
      setData(json);
    }

    fetchData();
  }, []);

  return <div>{data ? JSON.stringify(data) : "Loading..."}</div>;
}

Read more
Design process

Docker Basic Commands Cheat Sheet

This guide covers essential Docker commands and concepts, including:

  • Building images
  • Running containers
  • Managing processes
  • Cleaning up resources

It provides a clear understanding of the core Docker workflow with simple examples, enabling you to start building and running containerized applications confidently.

1. Build Docker Image

Create the image from your Dockerfile:

docker build -imagename(anyname) .

2. Run Docker Container

Start a container from the image:

docker run -p 3000:3000 imagename(anyname)

Port mapping:

  • 3000:3000 = local machine → container

3. List Containers

docker ps -a

Shows all containers (running + stopped)


4. Stop a Running Container

docker stop <container_id>

5. Remove a Container.

docker rm <container_id>

6. Remove Docker Image.

By name:

bash docker rmi dirname

### By image ID:
 ```bash
docker rmi <image_id>

Quick Flow (Important to remember)

build → run → list → stop → remove container → remove image

Read more