0% found this document useful (0 votes)
13 views28 pages

Software Engineering Guide

Uploaded by

philexybinti
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
13 views28 pages

Software Engineering Guide

Uploaded by

philexybinti
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

Software Engineering

A Complete Study Guide


Phase 1: Data Structures & Algorithms | Phase 2: System Design | Phase 3: DevOps &
Deployment

Beginner to Intermediate Level


Table of Contents
TOC \h \o "1-3"
PHASE 1
Data Structures & Algorithms

Data structures and algorithms are the building blocks of all software. A data structure is a way
of organizing information in memory so a program can use it efficiently. An algorithm is a step-
by-step procedure for solving a problem. Together, they determine how fast and efficient your
programs are.

Why it matters: Every app you use — Google Search, WhatsApp, Netflix — relies on
clever data structures and algorithms to work at scale. Understanding these concepts lets
you write code that doesn't just work, but works fast.

1.1 Big O Notation — The Language of Efficiency


Before learning specific data structures, you need a way to measure and compare their speed.
Big O notation describes how an algorithm's performance scales as the input size (n) grows. It
answers: "If I double the amount of data, how much longer does my program take?"

Common Big O Complexities


Notation Name Example
O(1) Constant Access array item by index
O(log n) Logarithmic Binary search in sorted list
O(n) Linear Loop through every item
O(n log n) Log-linear Efficient sorting (Merge Sort)
O(n²) Quadratic Nested loops — Bubble Sort
O(2ⁿ) Exponential Recursive Fibonacci (naive)

Key Rules for Calculating Big O


• Drop constants: O(2n) becomes O(n)
• Drop lower-order terms: O(n² + n) becomes O(n²)
• Worst case is the default unless specified otherwise
• Nested loops usually multiply: a loop inside a loop = O(n²)

Memory tip: Think of O(1) as a GPS that takes you directly to a destination, O(n) as
walking down a street checking each house, and O(n²) as checking every house against
every other house.

1.2 Arrays
An array is an ordered collection of items stored in contiguous (adjacent) memory slots. Each
slot has an index starting from 0. Arrays are the most fundamental data structure.

How Memory Works


When you create an array, the computer reserves a fixed block of consecutive memory slots.
Because each slot has a known size, the computer can jump directly to any index with a simple
math formula: address = base_address + (index × item_size). This is why access is O(1).

Operations & Complexity


Operation Complexity
Access by index (arr[3]) O(1) — instant, direct jump
Search (unsorted) O(n) — must check each item
Search (sorted, binary search) O(log n) — eliminates half each step
Insert at end O(1) — just add to next slot
Insert at middle/beginning O(n) — must shift items right
Delete from end O(1)
Delete from middle/beginning O(n) — must shift items left

Code Example (Python)


# Create an array (called a list in Python) fruits = ['apple', 'banana',
'cherry', 'date'] # Access by index — O(1) print(fruits[2]) # => 'cherry'
# Insert at end — O(1) [Link]('elderberry') # Insert at index 1 —
O(n), shifts everything right [Link](1, 'avocado') # Search — O(n)
print('banana' in fruits) # => True

When to Use Arrays


• You need fast access by index
• You know the size in advance or items mostly get added to the end
• You need ordered data that you'll iterate over frequently
When NOT to Use Arrays
• You frequently insert or delete items in the middle
• You don't know the size in advance (use a dynamic array / list instead)

1.3 Linked Lists


A linked list is a chain of nodes where each node holds a value and a pointer to the next node.
Unlike arrays, nodes don't need to be stored next to each other in memory — they can be
scattered anywhere, connected by these pointers.

Structure
Singly Linked: Each node points to the next. The last node points to null.
Doubly Linked: Each node points both forward and backward. Enables traversal in both
directions.
Circular: The last node points back to the first, forming a loop.

Operations & Complexity


Operation Complexity
Access by index O(n) — must walk from head
Search O(n) — must walk until found
Insert at head (beginning) O(1) — just update pointer
Insert at tail (end) O(1) with tail pointer, O(n) without
Insert in middle O(n) to find position, O(1) to insert
Delete from head O(1)
Delete from middle O(n) to find, O(1) to delete

Array vs Linked List — Head to Head


Array Linked List
O(1) access by index O(n) access by index
O(n) insert/delete at start O(1) insert/delete at start
Fixed or resizable block of memory Memory scattered, allocated per node
Better cache performance Poor cache performance (pointer jumping)
Use when access speed matters Use when insert/delete at ends matters
Real-world analogy: An array is a bookshelf with numbered slots — jump to any book
instantly. A linked list is a treasure hunt where each clue tells you where the next clue is —
you must follow the chain from the start.

1.4 Stacks & Queues


Stacks and queues are abstract data types — they describe a behaviour rather than a specific
implementation. Both can be built using arrays or linked lists.

Stack — Last In, First Out (LIFO)


A stack works like a pile of plates: you add to the top and remove from the top. The last item
added is the first one out.
Push: Add an item to the top — O(1)
Pop: Remove the top item — O(1)
Peek: View the top item without removing it — O(1)

Real-world uses: Undo/redo in a text editor, browser back button history, function call stack in
programming, expression evaluation.

Queue — First In, First Out (FIFO)


A queue works like a line at a checkout: first person in is the first person served.
Enqueue: Add to the back — O(1)
Dequeue: Remove from the front — O(1)

Real-world uses: Print spooler, task scheduling in operating systems, message queues in
distributed systems, BFS graph traversal.

Code Example (Python)


# Stack using Python list stack = [] [Link]('a') # push
[Link]('b') [Link]('c') print([Link]()) # => 'c' (LIFO) #
Queue using [Link] from collections import deque queue = deque()
[Link]('a') # enqueue [Link]('b') print([Link]()) # =>
'a' (FIFO)

1.5 Hash Maps (Hash Tables)


A hash map stores data as key-value pairs. It uses a hash function to convert a key into an
index, then stores the value at that index. This enables near-instant lookup, insertion, and
deletion regardless of how much data you have.
How It Works
1. You provide a key (e.g. 'username')
2. The hash function converts the key to a number (e.g. 42)
3. The value is stored at index 42 in an underlying array
4. To look up, hash the key again and jump directly to that index

Operations & Complexity


Operation Average / Worst Case
Lookup by key O(1) average / O(n) worst (collisions)
Insert O(1) average / O(n) worst
Delete O(1) average / O(n) worst
Search by value O(n) — must scan all values

Collisions
When two keys hash to the same index, a collision occurs. Two common solutions:
Chaining: Each slot holds a linked list of all items that hash there.
Open addressing: If a slot is taken, probe the next available slot.

Code Example (Python)


# Dictionary in Python IS a hash map user = {} user['name'] = 'Alice' #
insert — O(1) user['age'] = 30 print(user['name']) # lookup — O(1) del
user['age'] # delete — O(1) print('name' in user) # check
key — O(1) # Count word frequencies — classic hash map use text = 'the cat
sat on the mat' freq = {} for word in [Link](): freq[word] =
[Link](word, 0) + 1 print(freq) # {'the': 2, 'cat': 1, 'sat': 1, ...}

When to use a hash map: Any time you need fast lookup by a key — user sessions,
caches, counting occurrences, grouping data. Hash maps are one of the most used data
structures in real-world programming.

1.6 Trees & Binary Search Trees


A tree is a hierarchical data structure made of nodes, where each node has a value and zero or
more children. The top node is the root; nodes with no children are leaves.
Key Terms
Term Definition
Root The top node — has no parent
Leaf A node with no children
Height Longest path from root to a leaf
Depth Distance from a node to the root
Subtree A node and all its descendants

Binary Search Tree (BST)


A BST is a tree where each node has at most 2 children, and: all values in the left subtree are
smaller than the node, all values in the right subtree are larger.

Operation Complexity
Search O(log n) balanced / O(n) unbalanced
Insert O(log n) balanced / O(n) unbalanced
Delete O(log n) balanced / O(n) unbalanced

Tree Traversal Methods


In-order (Left → Root → Right): Visits nodes in sorted order in a BST.
Pre-order (Root → Left → Right): Useful for copying or serializing a tree.
Post-order (Left → Right → Root): Useful for deleting a tree.
BFS / Level-order: Visit nodes level by level using a queue.

Other Important Tree Types


AVL Tree: Self-balancing BST. Keeps height at O(log n) by rotating nodes after insertions.
Heap: Complete binary tree where parent is always greater (max-heap) or smaller (min-heap)
than children. Used in priority queues.
Trie: Tree for storing strings, where each node represents a character. Used in autocomplete.

1.7 Sorting Algorithms


Sorting algorithms arrange items in order. Knowing which to use when is an important
engineering skill.

Algorithm Time Complexity Key Property


Bubble Sort O(n²) average Simple but slow. Good for
learning only.
Selection Sort O(n²) average Finds the minimum each
pass.
Insertion Sort O(n²) avg, O(n) best Fast for nearly-sorted data.
Merge Sort O(n log n) always Divide and conquer. Stable.
Uses extra memory.
Quick Sort O(n log n) avg, O(n²) worst Fast in practice. In-place. Not
stable.
Heap Sort O(n log n) always In-place. Not stable.
Counting Sort O(n + k) Only for integers in a known
range.

Rule of thumb: For general use, Merge Sort or Quick Sort are your go-to choices. Python's
built-in sort (Timsort) is O(n log n) and combines Merge Sort and Insertion Sort for excellent
real-world performance.

1.8 Searching Algorithms

Linear Search
Check each item one by one until found. O(n). Works on unsorted data.

Binary Search
Only works on sorted data. Repeatedly halve the search space by comparing to the middle
element. O(log n) — extremely fast for large datasets.
def binary_search(arr, target): left, right = 0, len(arr) - 1 while
left <= right: mid = (left + right) // 2 if arr[mid] ==
target: return mid elif arr[mid] < target:
left = mid + 1 else: right = mid - 1 return -1 # not
found

Binary search insight: In a sorted list of 1 billion items, binary search finds any item in at
most 30 comparisons (log₂ 1,000,000,000 ≈ 30). Linear search would take up to 1 billion.

Phase 1 Quick Reference


Data Structure Best Used For
Array Indexed access, iteration, known-size
collections
Linked List Frequent insert/delete at head or tail
Stack Undo history, parsing, DFS traversal
Queue Task scheduling, BFS traversal, event buffers
Hash Map Fast key-value lookup, counting, grouping
BST Sorted data with fast search and insert
Heap Priority queues, finding min/max efficiently
PHASE 2
System Design & Architecture

System design is the process of defining the architecture, components, and data flow of a large
software system. It answers: how do you structure software that serves millions of users without
breaking? This is where junior engineers grow into senior engineers.

Why it matters: A correctly designed system can scale from 1,000 to 10,000,000 users. A
poorly designed system becomes a nightmare to maintain. System design knowledge is
heavily tested in senior software engineering interviews.

2.1 The Client-Server Model


Almost every application on the internet follows this model. A client (browser, mobile app)
makes requests. A server processes those requests and sends back responses.

How a Web Request Works


5. You type a URL into your browser (the client)
6. Your browser does a DNS lookup to find the server's IP address
7. A TCP connection is established (the 3-way handshake: SYN → SYN-ACK → ACK)
8. The browser sends an HTTP request: GET /page HTTP/1.1
9. The server processes the request, queries a database if needed
10. The server returns an HTTP response with the HTML/JSON data
11. The browser renders the page

HTTP Methods
Method Purpose
GET Retrieve data — should not change server
state
POST Create a new resource
PUT Replace an existing resource entirely
PATCH Update part of an existing resource
DELETE Remove a resource
HTTP Status Codes
Code Range Meaning
2xx (200, 201, 204) Success — 200 OK, 201 Created, 204 No
Content
3xx (301, 302) Redirect — resource has moved
4xx (400, 401, 403, 404) Client error — bad request, unauthorized,
forbidden, not found
5xx (500, 503) Server error — something broke on the
server side

2.2 APIs & REST


An API (Application Programming Interface) is a contract that defines how two pieces of
software talk to each other. REST (Representational State Transfer) is the most common style
for building web APIs.

REST Principles
• Stateless: each request contains all needed information — server keeps no session
state
• Resources: everything is a resource identified by a URL (e.g. /users/42)
• Uniform interface: standard HTTP methods and status codes
• Client-server separation: frontend and backend are independent

RESTful API Design Example


GET /users # list all users GET /users/42 # get user
with ID 42 POST /users # create a new user PUT /users/42
# replace user 42 entirely PATCH /users/42 # update part of user 42
DELETE /users/42 # delete user 42 GET /users/42/posts # get all
posts by user 42

GraphQL vs REST
REST GraphQL
Multiple endpoints (/users, /posts) Single endpoint (/graphql)
Server defines response shape Client specifies exact data needed
Can over-fetch or under-fetch Returns exactly what was requested
Simpler to understand and debug More flexible for complex queries
Best for simple, stable APIs Best for complex, data-heavy frontends

2.3 Databases
A database is an organized system for storing, retrieving, and managing data. Choosing the
right database type is one of the most important system design decisions.

SQL (Relational) Databases


Data is stored in tables with rows and columns. Tables relate to each other through foreign
keys. Uses SQL (Structured Query Language). Enforces a strict schema.
Examples: PostgreSQL, MySQL, SQLite, Microsoft SQL Server

Basic SQL
-- Create a table CREATE TABLE users ( id INTEGER PRIMARY KEY,
name TEXT NOT NULL, email TEXT UNIQUE, age INTEGER ); --
Insert a row INSERT INTO users (name, email, age) VALUES ('Alice',
'alice@[Link]', 30); -- Query data SELECT name, email FROM users WHERE
age > 25 ORDER BY name; -- Join two tables SELECT [Link], [Link]
FROM users JOIN posts ON [Link] = posts.user_id WHERE [Link] > 25;

NoSQL Databases
NoSQL databases sacrifice some relational features for flexibility and scale. No fixed schema —
data shape can vary per record.

Type Examples & Use Cases


Document store MongoDB, Firestore — JSON-like
documents, great for flexible schemas
Key-value store Redis, DynamoDB — ultra-fast lookup by
key, caching, sessions
Column-family Cassandra, HBase — massive scale, write-
heavy time-series data
Graph database Neo4j — relationships between entities,
social networks, recommendations

SQL vs NoSQL — When to Choose


Use SQL when... Use NoSQL when...
Data is highly structured Data shape varies per record
You need complex joins and queries You need massive horizontal scale
ACID transactions are required You need flexible, fast iteration
Example: financial systems, ERP Example: real-time feeds, user profiles

ACID Properties (SQL)


Atomicity: A transaction is all-or-nothing. If any step fails, everything is rolled back.
Consistency: Transactions bring the database from one valid state to another.
Isolation: Concurrent transactions don't interfere with each other.
Durability: Once committed, data survives crashes and power failures.

Indexing: A database index is like a book's index — it lets the database find rows without
scanning every row. Always index columns you search or join on frequently. Too many
indexes slow down writes.

2.4 Scalability Patterns


Scalability is a system's ability to handle more load. There are two fundamental approaches:

Vertical Scaling (Scale Up) Horizontal Scaling (Scale Out)


Add more power to one server (CPU, Add more servers
RAM)
Simpler — no code changes needed More complex — requires distributed thinking
Has a physical limit Theoretically unlimited
Single point of failure More fault-tolerant
Example: upgrade from 8GB to 64GB RAM Example: add 10 more web servers

Load Balancing
A load balancer sits in front of multiple servers and distributes incoming requests across them.
This prevents any single server from getting overwhelmed.
Round Robin: Distribute requests in order: server 1, 2, 3, 1, 2, 3...
Least Connections: Send to the server with fewest active connections.
IP Hash: Same user always goes to the same server (useful for session state).

Caching
A cache stores results of expensive operations so future requests can be served faster. It's one
of the most powerful performance tools.
Browser cache: Stores static files locally on the user's machine.
CDN (Content Delivery Network): Caches static assets close to users geographically.
Application cache (Redis): Stores expensive database query results in memory.
Database query cache: Database engine caches frequent query results.

Cache invalidation: The hardest problem in caching is knowing when data is stale.
Strategies: TTL (expire after N seconds), write-through (update cache when DB updates),
cache-aside (check cache first, fill on miss).

Database Sharding & Replication


Replication: Copy data to multiple database servers. One primary accepts writes; replicas
serve reads. Improves read performance and fault tolerance.
Sharding: Split data across multiple databases (e.g. users A-M on shard 1, N-Z on shard 2).
Allows massive horizontal scale but increases complexity.

2.5 Architecture Patterns

Monolithic Architecture
All components of the application are built and deployed as a single unit. The entire app shares
one codebase and one database.
Pros: Simple to develop, test, and deploy. Great for small teams and early-stage products.
Cons: Hard to scale individual components. One bug can take down the whole app. Slow to
deploy as it grows.

Microservices Architecture
The application is broken into many small, independent services, each responsible for one
business capability (auth service, payment service, notification service). Services communicate
via APIs or message queues.
Pros: Each service scales independently. Small teams own small services. Technology
flexibility.
Cons: Network latency between services. Distributed system complexity. Harder to test end-to-
end.

Event-Driven Architecture
Services communicate by publishing and consuming events via a message broker (Kafka,
RabbitMQ, SQS). The publisher doesn't know who consumes its events.
Use for: Real-time processing, decoupling services, handling traffic spikes, audit logs.

Monolith — Good for Microservices — Good for


Early-stage startup Large org with multiple teams
Simple domain logic Independent scaling needs
Small team (1-5 engineers) Complex domain with clear boundaries
Proving product-market fit High reliability requirements per service

Industry insight: Most successful companies (Amazon, Netflix, Uber) started as monoliths
and moved to microservices as they scaled. Don't design microservices from day one —
you'll create premature complexity.

2.6 Key System Design Concepts

CAP Theorem
In a distributed system, you can only guarantee two of three properties simultaneously:
Consistency (C): Every read receives the most recent write.
Availability (A): Every request receives a response (not necessarily the latest data).
Partition Tolerance (P): The system continues operating even when network failures split
nodes.
Since network partitions always happen in the real world, you must choose between C and A
during a partition. Most modern databases are either CP (e.g. HBase, MongoDB in strict mode)
or AP (e.g. DynamoDB, Cassandra).

Message Queues
A message queue buffers work between producers and consumers. The producer sends a
message and moves on; a worker picks it up asynchronously.
Use for: Background jobs (sending emails, resizing images), handling traffic spikes, decoupling
services.
Tools: RabbitMQ (traditional), Apache Kafka (high-throughput streaming), AWS SQS
(managed).

Consistent Hashing
A technique for distributing data across servers in a way that minimizes redistribution when
servers are added or removed. Critical for building scalable distributed caches and databases.
Designing for Failure
Timeout: Never wait forever for a response. Set a timeout and fail gracefully.
Retry with backoff: On failure, retry with increasing delays (1s, 2s, 4s, 8s).
Circuit breaker: If a downstream service keeps failing, stop calling it for a period and return a
default response.
Graceful degradation: If the recommendation engine is down, show generic recommendations
rather than crashing.
PHASE 3
DevOps & Deployment

DevOps (Development + Operations) is the practice of unifying software development and IT


operations to shorten the delivery cycle. It's how code goes from a developer's laptop to
production in a reliable, repeatable way.

Why it matters: A feature no one can use is worth nothing. DevOps skills let you ship code
confidently, roll back safely, and keep systems running 24/7. Modern engineering expects
developers to understand how their code is deployed.

3.1 Git & Version Control


Git is the world's most widely used version control system. It tracks every change to your code,
lets you work on features in isolation (branches), and enables teams to collaborate without
overwriting each other's work.

Core Concepts
Repository (repo): A folder tracked by Git. Contains all files and their full history.
Commit: A snapshot of your changes at a point in time. The building block of Git history.
Branch: An independent line of development. main is the default. Features get their own
branches.
Merge: Combine changes from one branch into another.
Pull Request (PR): A proposal to merge a branch, used for code review before merging.
Remote: A copy of the repository on a server (e.g. GitHub, GitLab).

Essential Git Commands


Command What It Does
git init Initialize a new repository in current folder
git clone <url> Download a remote repository to your
machine
git status Show which files have changed
git add <file> Stage changes for the next commit
git add . Stage ALL changed files
git commit -m 'message' Save staged changes as a commit
git push origin main Upload commits to the remote main branch
git pull Download and merge latest changes from
remote
git branch feature-x Create a new branch named feature-x
git checkout feature-x Switch to the feature-x branch
git merge feature-x Merge feature-x into your current branch
git log --oneline See commit history, one line per commit
git diff See what changed but hasn't been staged
yet
git stash Temporarily save changes without
committing
git revert <hash> Safely undo a commit by creating a new one

Branching Strategy — Git Flow


main: Always production-ready. Only merge via PR. Protected from direct pushes.
develop: Integration branch. Features merge here first.
feature/x: One branch per feature. Created from develop, merged back via PR.
hotfix/x: Emergency fixes branched directly from main.

Good commit messages: Use the imperative mood: 'Add login endpoint' not 'Added login'
or 'Adding login'. Include the why, not just the what. Bad: 'fix bug'. Good: 'Fix null pointer
crash when user has no email set'.

3.2 CI/CD Pipelines


CI/CD stands for Continuous Integration / Continuous Delivery (or Deployment). It's the
automation that takes code from a developer's commit to running in production with minimal
human intervention.

Continuous Integration (CI)


Every time a developer pushes code, the CI system automatically: builds the code, runs all
tests, and reports whether the build passed or failed. This catches bugs immediately rather than
weeks later.
• Run unit tests
• Run integration tests
• Lint and format checks
• Security vulnerability scanning
• Build Docker images

Continuous Delivery vs Continuous Deployment


Continuous Delivery Continuous Deployment
Code is always in a deployable state Every passing build auto-deploys to
production
Deployment requires a human approval No human intervention after merge
step
Lower risk, more control Faster, requires excellent test coverage
Common in regulated industries Common in high-velocity tech companies

Popular CI/CD Tools


• GitHub Actions — built into GitHub, YAML-based, very popular
• GitLab CI — built into GitLab, powerful pipelines
• Jenkins — open-source, highly configurable, self-hosted
• CircleCI — fast, cloud-hosted
• AWS CodePipeline — native AWS integration

Example GitHub Actions Workflow


# .github/workflows/[Link] name: CI Pipeline on: push: branches: [main,
develop] pull_request: jobs: test: runs-on: ubuntu-latest steps:
- uses: actions/checkout@v3 - uses: actions/setup-python@v4
with: python-version: '3.11' - run: pip install -r
[Link] - run: pytest tests/ - run: flake8 . # lint
check

3.3 Docker & Containers


A container packages your application and all its dependencies (libraries, runtime, config) into a
single portable unit. It runs the same way on any machine — your laptop, a test server, or a
cloud server.

Containers vs Virtual Machines


Container Virtual Machine
Shares the host OS kernel Runs its own full OS
Starts in milliseconds Starts in minutes
Uses ~MBs of RAM Uses ~GBs of RAM
Less isolation Strong isolation
Docker, containerd VMware, VirtualBox, KVM

Key Docker Concepts


Dockerfile: A text file with instructions for building a Docker image.
Image: A read-only template built from a Dockerfile. Like a class in OOP.
Container: A running instance of an image. Like an object in OOP.
Registry: A storage service for images. Docker Hub is the public registry; AWS ECR is private.
docker-compose: A tool to define and run multi-container applications (app + database +
cache) locally.

Example Dockerfile
# Start from official Python 3.11 image FROM python:3.11-slim # Set working
directory inside the container WORKDIR /app # Copy dependency list and
install COPY [Link] . RUN pip install --no-cache-dir -r
[Link] # Copy application code COPY . . # Expose port 8000 EXPOSE
8000 # Start the app CMD ["python", "-m", "uvicorn", "main:app", "--host",
"[Link]", "--port", "8000"]

Essential Docker Commands


Command What It Does
docker build -t myapp . Build an image named myapp from current
directory
docker run -p 8000:8000 myapp Start a container, map port 8000
docker ps List running containers
docker stop <id> Stop a running container
docker logs <id> View container output logs
docker-compose up Start all services defined in docker-
[Link]
docker-compose down Stop and remove all services
docker pull nginx Download the nginx image from Docker Hub
3.4 Kubernetes (K8s)
Kubernetes is a container orchestration platform — it manages running containers across a
cluster of machines. It handles scheduling, scaling, healing, and updating containers
automatically.

Key Concepts
Cluster: A set of machines (nodes) managed by Kubernetes.
Node: A single machine in the cluster (physical or virtual).
Pod: The smallest deployable unit in K8s. Usually wraps one container.
Deployment: Declares the desired state — run 3 replicas of this pod. K8s ensures it.
Service: A stable network endpoint for reaching a set of pods (load balancing within the
cluster).
Ingress: Routes external HTTP traffic to services inside the cluster.
ConfigMap / Secret: Inject configuration and secrets into pods without hardcoding them.

When to use K8s: Kubernetes adds significant complexity. Don't use it for side projects or
small apps. Consider it when you have many services to manage, need auto-scaling, or
have a dedicated DevOps team.

3.5 Cloud Computing Basics


Cloud computing is renting computing resources (servers, storage, databases, networking) from
a provider over the internet instead of owning physical hardware.

The Three Big Providers


• AWS (Amazon Web Services) — largest market share, most services
• Google Cloud Platform (GCP) — strong in data, ML, and Kubernetes
• Microsoft Azure — strong in enterprise and Windows environments

Service Models
Model What You Manage vs Provider
IaaS (Infrastructure as a Service) You manage OS, runtime, app. Provider
manages hardware. Example: AWS EC2
PaaS (Platform as a Service) You manage just your app. Provider
manages OS, runtime, scaling. Example:
Heroku, [Link]
SaaS (Software as a Service) You use a finished product. Everything
managed by provider. Example: Gmail,
Notion
FaaS / Serverless You write functions. Provider manages
everything else. Example: AWS Lambda

Core AWS Services to Know


Service Purpose
EC2 Virtual machines — rent a Linux server
S3 Object storage — store files, images,
backups
RDS Managed relational databases (PostgreSQL,
MySQL)
Lambda Serverless functions — run code without a
server
CloudFront CDN — serve content fast globally
VPC Virtual private network — isolate your
resources
IAM Identity & access management — control
who can do what
ECS / EKS Container hosting (ECS = AWS native, EKS
= Kubernetes)
SQS Managed message queue
CloudWatch Monitoring, logging, and alerting

3.6 Infrastructure as Code (IaC)


Infrastructure as Code means defining your servers, databases, and networks in code files
rather than manually clicking through dashboards. This makes infrastructure reproducible,
version-controlled, and auditable.

Key Tools
Terraform: Provider-agnostic IaC tool. Define infrastructure in HCL files. Widely used for AWS,
GCP, Azure. The most popular choice.
AWS CloudFormation: AWS-native IaC using YAML/JSON. Tightly integrated with AWS
services.
Ansible: Configuration management — automate software installation and server setup.
Pulumi: Write IaC in Python/TypeScript/Go instead of DSL files.

Terraform Example
# [Link] — create an AWS EC2 instance provider "aws" { region = "us-east-1"
} resource "aws_instance" "web" { ami = "ami-0c55b159cbfafe1f0"
# Amazon Linux 2 instance_type = "[Link]" tags = { Name = "my-web-
server" } } # Commands: # terraform init — download providers #
terraform plan — preview changes # terraform apply — create the resources
# terraform destroy — tear everything down

3.7 Monitoring, Logging & Alerting


You can't fix what you can't see. Observability is the practice of understanding your system's
internal state from its external outputs.

The Three Pillars of Observability


Metrics: Numerical measurements over time. CPU usage, request rate, error rate, latency.
Stored in time-series databases (Prometheus, Datadog).
Logs: Detailed records of events. Every request, error, and state change. Centralized with tools
like ELK Stack (Elasticsearch, Logstash, Kibana) or Loki.
Traces: Track a single request as it flows through multiple services. Shows exactly where time
was spent. Tools: Jaeger, Zipkin, AWS X-Ray.

Key Metrics to Monitor


• Latency — p50, p95, p99 response times (percentiles, not just averages)
• Error rate — percentage of requests that return 5xx errors
• Request rate — requests per second (traffic volume)
• Saturation — how full is your system? CPU %, queue depth, disk usage

The four golden signals: Google's SRE book defines four golden signals: Latency, Traffic,
Errors, and Saturation. Monitor these four for any service and you'll catch 90% of production
issues.

Alerting Best Practices


• Alert on symptoms, not causes. Alert when users are affected, not on every metric spike.
• Set SLOs (Service Level Objectives) — e.g. 99.9% of requests complete within 500ms.
• Avoid alert fatigue — too many noisy alerts get ignored. Be selective.
• Include a runbook link in every alert: what should the on-call engineer do?
3.8 Security Fundamentals

Authentication vs Authorization
Authentication (AuthN) Authorization (AuthZ)
Who are you? What are you allowed to do?
Verifying identity Checking permissions
Login with password, OAuth, 2FA Role-based access control (RBAC)
Example: JWT token verification Example: can this user delete this post?

Common Security Vulnerabilities (OWASP Top 10)


• SQL Injection — attacker injects SQL code via user input. Always use parameterized
queries.
• Broken Authentication — weak passwords, exposed tokens, session fixation.
• XSS (Cross-Site Scripting) — injecting malicious scripts into web pages. Escape all user
output.
• CSRF (Cross-Site Request Forgery) — tricking users into making unintended requests.
Use CSRF tokens.
• Insecure Direct Object Reference — exposing internal IDs without authorization checks.
• Security Misconfiguration — default credentials, open S3 buckets, verbose error
messages.

Security Best Practices


• Never store plain text passwords — always hash with bcrypt or Argon2
• Use HTTPS everywhere — encrypt data in transit with TLS
• Principle of least privilege — give services and users only the permissions they need
• Environment variables for secrets — never commit API keys or passwords to git
• Regular dependency updates — patch known vulnerabilities in libraries
• Input validation — validate and sanitize all user input on the server side
Master Cheat Sheet

Big O Quick Reference


Notation Speed When You See It
O(1) Instant Array index, hash map
get/set
O(log n) Very fast Binary search, balanced BST
ops
O(n) Linear Single loop, linear search
O(n log n) Good Efficient sorting algorithms
O(n²) Slow Nested loops, bubble sort
O(2ⁿ) Terrible Exponential recursion

Data Structure Selection Guide


Scenario Use This Why
Fast lookup by index Array O(1) access
Fast lookup by key Hash Map O(1) average lookup
Frequent insert/delete at Linked List or Deque O(1) head/tail ops
ends
LIFO: undo, call stack Stack Last in, first out
FIFO: task queue, BFS Queue First in, first out
Sorted data, fast search BST or sorted array O(log n) ops
Priority (min/max always Heap O(1) peek, O(log n) insert
available)
Autocomplete, prefix search Trie O(m) lookup, m = word
length

System Design Checklist


When tackling any system design problem, work through these questions:
12. Clarify requirements — how many users? Reads vs writes? Latency requirements? Data
size?
13. Estimate scale — requests per second, storage needed, bandwidth
14. Define the API — what endpoints / interfaces does the system expose?
15. Design the data model — what do you store? SQL or NoSQL?
16. Draw the high-level architecture — clients, load balancers, services, databases, caches
17. Identify bottlenecks — what breaks first at 10x scale?
18. Address bottlenecks — caching, sharding, read replicas, CDN, async processing
19. Consider failure scenarios — what happens if the database goes down?

DevOps Deployment Checklist


For any new service going to production:
• Code reviewed and merged via PR
• CI pipeline passes (tests, lint, security scan)
• Docker image built and pushed to registry
• Secrets stored in environment variables, not in code
• Infrastructure defined in code (Terraform)
• Health check endpoint exists (/health returns 200)
• Logging structured (JSON format with correlation IDs)
• Metrics and alerts configured
• Runbook written for on-call team
• Rollback plan documented

Recommended Learning Path


Topic Resources
Python basics (if needed) [Link] docs, Automate the Boring Stuff
(free)
Data Structures & Algorithms LeetCode (start Easy), [Link] roadmap
Git Pro Git book (free online), GitHub Skills
SQL [Link], PostgreSQL official tutorial
System Design System Design Primer (GitHub), Alex Xu's
books
Docker Docker official getting started, Play with
Docker
Cloud (AWS) AWS free tier, Cloud Practitioner cert for
foundations
CI/CD GitHub Actions docs, build a pipeline for a
pet project

Good luck on your software engineering journey!

You might also like