Tech With Htunn
  • Blog Content
  • ๐Ÿค–Artificial Intelligence
    • ๐Ÿง Building an Intelligent Agent with Local LLMs and Azure OpenAI
    • ๐Ÿ“ŠRevolutionizing IoT Monitoring: My Personal Journey with LLM-Powered Observability
  • ๐Ÿ“˜Core Concepts
    • ๐Ÿ”„Understanding DevSecOps
    • โฌ…๏ธShifting Left in DevSecOps
    • ๐Ÿ“ฆUnderstanding Containerization
    • โš™๏ธWhat is Site Reliability Engineering?
    • โฑ๏ธUnderstanding Toil in SRE
    • ๐Ÿ”What is Identity and Access Management?
    • ๐Ÿ“ŠMicrosoft Graph API: An Overview
    • ๐Ÿ”„Understanding Identity Brokers
  • ๐Ÿ”ŽSecurity Testing
    • ๐Ÿ”SAST vs DAST: Understanding the Differences
    • ๐ŸงฉSoftware Composition Analysis (SCA)
    • ๐Ÿ“‹Software Bill of Materials (SBOM)
    • ๐ŸงชDependency Scanning in DevSecOps
    • ๐ŸณContainer Scanning in DevSecOps
  • ๐Ÿ”„CI/CD Pipeline
    • ๐Ÿ”My Journey with Continuous Integration in DevOps
    • ๐Ÿš€My Journey with Continuous Delivery and Deployment in DevOps
  • ๐ŸงฎFundamentals
    • ๐Ÿ’พWhat is Data Engineering?
    • ๐Ÿ”„Understanding DataOps
    • ๐Ÿ‘ทThe Role of a Cloud Architect
    • ๐Ÿ›๏ธCloud Native Architecture
    • ๐Ÿ’ปCloud Native Applications
  • ๐Ÿ›๏ธArchitecture & Patterns
    • ๐Ÿ…Medallion Architecture in Data Engineering
    • ๐Ÿ”„ETL vs ELT Pipeline: Understanding the Differences
  • ๐Ÿ”’Authentication & Authorization
    • ๐Ÿ”‘OAuth 2.0 vs OIDC: Key Differences
    • ๐Ÿ”Understanding PKCE in OAuth 2.0
    • ๐Ÿ”„Service Provider vs Identity Provider Initiated SAML Flows
  • ๐Ÿ“‹Provisioning Standards
    • ๐Ÿ“ŠSCIM in Identity and Access Management
    • ๐Ÿ“กUnderstanding SCIM Streaming
  • ๐Ÿ—๏ธDesign Patterns
    • โšกEvent-Driven Architecture
    • ๐Ÿ”’Web Application Firewalls
  • ๐Ÿ“ŠReliability Metrics
    • ๐Ÿ’ฐError Budgets in SRE
    • ๐Ÿ“SLA vs SLO vs SLI: Understanding the Differences
    • โฑ๏ธMean Time to Recovery (MTTR)
Powered by GitBook
On this page
  • My Understanding of Cloud-Native Applications
  • The Key Pillars of Cloud-Native Development (From My Experience)
  • My Real-World Example: Building a Python Microservice for AWS Lambda
  • Step 1: Setting Up My Development Environment
  • Step 2: Creating a Simple Python Lambda Function
  • Step 3: Defining the Infrastructure as Code with Serverless Framework
  • Step 4: Implementing Additional CRUD Operations
  • Step 5: Deploying to AWS Lambda
  • Why This Approach Changed How I Build Software
  • What I've Learned Along The Way
  1. Fundamentals

Cloud Native Applications

After spending years building traditional monolithic applications, my transition to cloud-native development was nothing short of transformative. Let me share what I've learned about cloud-native applications and how they've changed the way I approach software engineering.

My Understanding of Cloud-Native Applications

In my experience, cloud-native applications are fundamentally different from traditional applications. They're not just applications that run in the cloud; they're applications that are born in the cloud and designed to exploit everything the cloud has to offer.

When I first started building cloud-native apps, I had to shift my mindset. I wasn't just lifting and shifting existing applicationsโ€”I was rethinking how applications should be designed, built, and operated in a cloud environment.

The Key Pillars of Cloud-Native Development (From My Experience)

  1. Microservices Architecture: I used to build monoliths where everything was tightly coupled. Now I break applications into specialized, loosely-coupled services that can evolve independently. This has been a game-changer for my team's productivity.

  2. Containerization & Orchestration: Packaging my microservices in containers eliminated the "it works on my machine" problem. Now my applications run consistently across development, testing, and production environments.

  3. DevOps Culture: I've embraced the blending of development and operations. By automating infrastructure provisioning and deployments, I've been able to focus more on building features than managing servers.

  4. Serverless Computing: This was a paradigm shift for meโ€”writing code without thinking about the underlying infrastructure. My functions just run when needed, and I only pay for what I use.

  5. CI/CD Pipelines: Automating the build, test, and deployment process has allowed my team to release multiple times a day rather than once a quarter.

My Real-World Example: Building a Python Microservice for AWS Lambda

Let me walk you through how I built a simple but powerful cloud-native application using Python and AWS Lambdaโ€”something I've done numerous times for production systems.

Step 1: Setting Up My Development Environment

First, I make sure I have the right tools installed:

# Install AWS CLI and configure credentials
brew install awscli
aws configure

# Install Python dependencies manager and serverless framework
pip install pipenv
npm install -g serverless

Step 2: Creating a Simple Python Lambda Function

I start with a basic structure for my user management service:

mkdir user-service
cd user-service
pipenv --python 3.9
pipenv install boto3 pymongo

Then I create the main function handler:

# handler.py
import json
import boto3
import os
import datetime
from pymongo import MongoClient

# Initialize database connection (using AWS Secrets Manager in production)
def get_db_connection():
    client = MongoClient(os.environ['MONGODB_URI'])
    return client.user_database

# Lambda handler for creating users
def create_user(event, context):
    try:
        # Parse request body
        body = json.loads(event['body'])
        
        # Connect to database
        db = get_db_connection()
        
        # Insert user
        result = db.users.insert_one({
            'name': body['name'],
            'email': body['email'],
            'created_at': str(datetime.datetime.now())
        })
        
        # Return success response
        return {
            'statusCode': 201,
            'headers': {'Content-Type': 'application/json'},
            'body': json.dumps({'userId': str(result.inserted_id)})
        }
    except Exception as e:
        # Error handling
        return {
            'statusCode': 500,
            'body': json.dumps({'error': str(e)})
        }

Step 3: Defining the Infrastructure as Code with Serverless Framework

One of my biggest learnings was to treat infrastructure as code. Here's how I define my Lambda function and API Gateway:

# serverless.yml
service: user-service

provider:
  name: aws
  runtime: python3.9
  region: us-east-1
  environment:
    MONGODB_URI: ${ssm:/user-service/mongodb-uri}
  iamRoleStatements:
    - Effect: Allow
      Action:
        - secretsmanager:GetSecretValue
      Resource: arn:aws:secretsmanager:${self:provider.region}:*:secret:user-service/*

functions:
  createUser:
    handler: handler.create_user
    events:
      - http:
          path: users
          method: post
          cors: true
  
  getUsers:
    handler: handler.get_users
    events:
      - http:
          path: users
          method: get
          cors: true

Step 4: Implementing Additional CRUD Operations

I expand the service with more endpoints:

# Additional handlers in handler.py

# Get all users
def get_users(event, context):
    try:
        db = get_db_connection()
        users = list(db.users.find({}, {'_id': 0}))
        
        return {
            'statusCode': 200,
            'headers': {'Content-Type': 'application/json'},
            'body': json.dumps(users)
        }
    except Exception as e:
        return {
            'statusCode': 500,
            'body': json.dumps({'error': str(e)})
        }

# Get user by ID
def get_user(event, context):
    try:
        user_id = event['pathParameters']['id']
        db = get_db_connection()
        
        user = db.users.find_one({'_id': user_id}, {'_id': 0})
        if not user:
            return {
                'statusCode': 404,
                'body': json.dumps({'message': 'User not found'})
            }
            
        return {
            'statusCode': 200,
            'headers': {'Content-Type': 'application/json'},
            'body': json.dumps(user)
        }
    except Exception as e:
        return {
            'statusCode': 500,
            'body': json.dumps({'error': str(e)})
        }

Step 5: Deploying to AWS Lambda

The deployment process becomes incredibly simple:

# Deploy to AWS
serverless deploy

# Output will show API endpoints

Why This Approach Changed How I Build Software

After building several applications this way, I've experienced firsthand the benefits of cloud-native development:

  1. True Scalability: My Lambda functions automatically scale from a few requests to thousands per second without any intervention.

  2. Cost Efficiency: I'm only charged when my functions executeโ€”during quiet periods, I pay nothing instead of maintaining idle servers.

  3. Development Speed: My team can work on separate services independently, accelerating our development cycle dramatically.

  4. Operational Simplicity: AWS handles all the underlying infrastructure, allowing me to focus on business logic.

  5. Built-in Resilience: By design, each function is isolated, preventing cascading failures that plagued my monolithic apps.

What I've Learned Along The Way

Building cloud-native applications isn't without challenges. Here are some lessons I've learned the hard way:

  • Cold starts can be an issue: First invocation of Lambda functions can be slow, so I've learned optimization techniques like provisioned concurrency for critical paths.

  • Distributed debugging is complex: I had to invest in proper logging and monitoring to trace requests across multiple services.

  • State management requires thought: With stateless functions, you need to carefully consider where state lives (typically in databases or cache).

  • Function size matters: Breaking down services too small can lead to excessive network calls and complexity.

Cloud-native development has fundamentally changed how I approach software engineering. The combination of Python's simplicity with AWS Lambda's serverless model has enabled me to build applications that are more resilient, cost-effective, and scalable than I ever could with traditional architectures.

PreviousCloud Native ArchitectureNextMedallion Architecture in Data Engineering

Last updated 21 hours ago

๐Ÿงฎ
๐Ÿ’ป