Skip to main content

Documentation Index

Fetch the complete documentation index at: https://resources.devweekends.com/llms.txt

Use this file to discover all available pages before exploring further.

Why Learn Engineering Fundamentals?

Strong engineering fundamentals separate good developers from great ones. Frameworks change every few years, but the principles behind them — how operating systems manage memory, how networks route packets, how databases maintain consistency — have remained remarkably stable for decades. An engineer who understands fundamentals can learn any new framework in weeks because they already understand the “why” behind the “what.” These topics help you:
  • Design scalable and maintainable systems from first principles, not by copying tutorials
  • Debug complex issues efficiently by reasoning about what the system is actually doing under the hood
  • Communicate technical decisions clearly using precise vocabulary that signals competence
  • Excel in system design interviews where interviewers test depth of understanding, not memorized patterns
  • Build production-ready applications that survive real-world traffic, failures, and changing requirements
Career Impact: Engineers with strong fundamentals are 3x more likely to be promoted to senior roles and consistently outperform in technical interviews at top companies. This is not because they memorize more — it is because they can reason from principles when they encounter problems they have never seen before, which is exactly what senior engineering roles demand.

Topic Categories

Computer Science Fundamentals

OS, Networks, Databases, Computer Architecture, and Distributed Systems basics

Software Design Principles

SOLID, DRY, KISS, Design Patterns, and Clean Code practices

Architecture Patterns

Microservices, Monolith, Event-Driven, DDD, Hexagonal, and more

DevOps & Infrastructure

CI/CD, Containers, Kubernetes, IaC, GitOps, and SRE

Security Fundamentals

Authentication, Authorization, Encryption, OWASP, and API Security

Performance & Optimization

Caching, Profiling, Load Testing, Async Processing, and Scaling

Learning Path

This is an 8-week progressive curriculum. Each step builds on the previous one — resist the temptation to skip ahead. Understanding why a circuit breaker pattern exists requires first understanding distributed system failure modes, which requires understanding networking fundamentals.
1

Foundation (Week 1-2)

Start with CS Fundamentals — understand how computers, networks, and databases work at a fundamental level. Master processes, threads, TCP/IP, and ACID properties. This is the bedrock everything else sits on. Without it, you will memorize patterns without understanding when and why to apply them.
2

Design Principles (Week 3-4)

Master SOLID principles, Design Patterns, and Clean Code practices. These form the foundation of all professional software. Focus on understanding the “why” behind each principle, not just the code examples. The goal is to develop an instinct for code structure.
3

Architecture (Week 5-6)

Learn different architecture patterns (Monolith, Microservices, Event-Driven) and when to apply each. Understand trade-offs and DDD concepts. This is where design principles scale from individual classes to entire systems. The key skill: evaluating which pattern fits your specific constraints (team size, domain complexity, scale requirements).
4

Operations (Week 7-8)

Dive into DevOps, Security, and Performance optimization for production-ready systems. Learn CI/CD, monitoring, and scaling strategies. This is where theoretical knowledge meets reality — a beautiful architecture that cannot be deployed, monitored, or secured is worthless.

Topic Difficulty Matrix

TopicDifficultyInterview FrequencyTime to Learn
CS Fundamentals🟡 MediumVery High2-3 weeks
SOLID Principles🟢 EasyVery High1 week
Clean Code🟢 EasyHigh1 week
Design Patterns🟡 MediumVery High2-3 weeks
Microservices🟡 MediumHigh2 weeks
DDD & Hexagonal🔴 HardMedium2-3 weeks
DevOps Basics🟡 MediumMedium2 weeks
Kubernetes🔴 HardMedium3-4 weeks
Security🟡 MediumMedium2 weeks
Performance🔴 HardMedium2-3 weeks

What You’ll Learn

Computer Science Fundamentals

  • Process vs Thread, Memory Management, Deadlocks
  • TCP/IP, HTTP/1.1 vs HTTP/2 vs HTTP/3, WebSockets
  • ACID, Transaction Isolation, Indexing, CAP Theorem
  • CPU Cache Hierarchy, Latency Numbers

Design Principles & Patterns

  • SOLID, DRY, KISS, YAGNI, Law of Demeter
  • Creational: Singleton, Factory, Builder
  • Structural: Adapter, Decorator, Facade
  • Behavioral: Strategy, Observer, Command

Architecture Patterns

  • Monolith vs Microservices vs Modular Monolith
  • Event-Driven, CQRS, Event Sourcing
  • Hexagonal Architecture, DDD Concepts
  • Saga Pattern, Circuit Breaker, API Gateway

DevOps & SRE

  • CI/CD Pipelines, GitOps
  • Docker, Kubernetes, Helm
  • Terraform, Infrastructure as Code
  • Monitoring, Logging, Tracing (Observability)
  • SLIs, SLOs, SLAs, Error Budgets

Security

  • Authentication (JWT, OAuth 2.0) & Authorization (RBAC)
  • OWASP Top 10 Vulnerabilities
  • Encryption, HTTPS/TLS, Secrets Management
  • API Security, CORS, CSP

Performance

  • Caching Strategies (Cache-Aside, Write-Through)
  • Database Optimization, N+1 Problem
  • Load Testing, Profiling
  • Horizontal vs Vertical Scaling
Pro Tip: Don’t just read about these concepts — build projects that use them. Hands-on experience solidifies understanding in a way that reading alone never will. Try implementing a small e-commerce system: a monolith with SOLID principles, then extract one microservice, add a CI/CD pipeline, write load tests, and observe what happens under stress. You will learn more from one weekend of building than from a month of reading.
Common Mistake: Trying to learn everything at once. Focus on fundamentals first, then progressively add complexity. Master one topic before moving to the next. Depth beats breadth — an engineer who deeply understands database indexing and can explain B-tree traversal is more valuable than one who can name 20 design patterns but cannot implement any of them.

Interview Deep-Dive

Strong Answer:
  • The instinct is to fix everything at once, but that is a trap. You have three problems (no tests, no monitoring, manual deploys), and the right order matters because each layer builds on the previous one.
  • I start with monitoring, not tests. Here is why: you cannot improve what you cannot measure, and right now, you do not even know if the system is healthy. Add the Four Golden Signals (latency, traffic, errors, saturation) using Prometheus + Grafana or a managed service like Datadog. Instrument the top 5 API endpoints with request duration histograms and error rate counters. Set up a basic PagerDuty alert: “if 5xx error rate exceeds 5% for 3 minutes, page the on-call.” This takes 2-3 days and gives you a safety net immediately.
  • Next, I add a CI/CD pipeline — even a basic one. A GitHub Actions workflow that builds the project and deploys to a staging environment on merge to main. This eliminates the SSH-to-production pattern, which is the highest risk item. Every deployment through the pipeline is logged, reversible, and consistent. No tests in the pipeline yet — that comes next. This takes 1-2 days.
  • Then, I write integration tests for the critical path. Not aiming for 80% coverage — aiming for the top 3 user journeys that, if broken, would be an incident. Run these in the CI pipeline as a gate. Now deployments are automated AND validated. This takes 1-2 weeks of incremental work alongside feature development.
  • Throughout all of this, I am documenting what I find: the architecture, the deployment process, the failure modes I discover. The new team member who joins after me should not have to rediscover everything from scratch.
  • What I would NOT do: propose a 3-month “stability sprint” where the team writes no features. Leadership will not approve it, the team will resent it, and you will not have the context yet to make good decisions about what to test. Instead, bake improvements into daily work: every PR that touches a file adds a test for the code it changes.
Follow-up: The team lead says “we have been meaning to add tests for two years but never had time.” How do you create a culture shift around testing without being the new person who lectures everyone?I lead by example, not by mandate. In my first PRs, I include tests for the code I am changing and make them obviously useful — catch a real bug in the test, then mention it casually in the PR description: “Added a test for the discount calculation and found it was returning the wrong value for orders over $1,000. Fixed that too.” When teammates see tests catching real bugs rather than being a bureaucratic checkbox, the resistance drops. I also make it easy: set up the test infrastructure so writing a test is a 5-minute effort (test fixtures, database seeds, helper functions). The biggest barrier to testing is not philosophy — it is friction. If writing one test requires 30 minutes of setup, nobody will do it. If it requires 5 minutes, people will do it naturally.
Strong Answer:
  • SOLID principles and architecture patterns are the same ideas operating at different scales. What SRP is to a class, a bounded context is to a system. What DIP is to a module, an API contract is to a microservice. Understanding this fractal relationship is what separates an engineer who can design a class from one who can design a system.
  • Single Responsibility at the class level: one class should have one reason to change. At the system level: one microservice should own one business domain. The Order service handles orders, not orders AND inventory AND notifications. If you violate SRP at the system level, you get a distributed monolith where changing the inventory logic requires redeploying the order service.
  • Open/Closed at the class level: add new behavior through extension (new classes implementing an interface), not modification. At the system level: add new capabilities by deploying new services that subscribe to existing events, not by modifying existing services. An event-driven architecture is the system-level manifestation of OCP — the Order service publishes “OrderPlaced” events and does not know or care how many downstream services consume them. Adding a Loyalty Points service requires zero changes to the Order service.
  • Dependency Inversion at the class level: depend on abstractions (interfaces), not concretions. At the system level: services communicate through well-defined API contracts or event schemas, not through shared databases or internal implementation details. A service mesh enforces this at the infrastructure level.
  • The key insight for interviews: when a system design question asks you to decompose a large system, you are applying SOLID at the architecture scale. The skills you learned writing clean classes directly transfer to drawing clean service boundaries.
Follow-up: Can you give me an example where following SOLID at the class level actually conflicts with a good architecture decision at the system level?Yes — DRY is the clearest case. At the class level, DRY says extract shared logic into a common function. At the system level, extracting shared logic into a shared library between microservices creates deployment coupling. If the User service and the Order service both need an “address validation” function, the class-level DRY instinct says put it in a shared library. But the architecture-level principle says each service should be independently deployable — so you either duplicate the function in both services or extract it into its own microservice with an API. Another example: Liskov Substitution encourages polymorphism and shared type hierarchies. But in a microservices architecture, shared types between services are a code smell — each service should define its own internal models, even if they look similar, because they serve different purposes in different bounded contexts. The right answer in an interview is to acknowledge this tension explicitly: “Principles are context-dependent. What is good engineering at the class level may be an anti-pattern at the system level, and the skill is recognizing which level you are operating at.”
Strong Answer:
  • At 1,000 DAU with 5 engineers, the architecture should be a well-structured monolith deployed on a single server or a small managed service (Heroku, Render, Railway, or a single ECS/Cloud Run instance). A PostgreSQL database with proper indexes handles this scale trivially. Redis for session storage and basic caching. That is it.
  • What I would tell them NOT to do: Do not adopt Kubernetes. Do not build microservices. Do not implement event sourcing. Do not set up a Kafka cluster. Each of these is a full-time job to operate, and with 5 engineers you cannot afford to spend 40% of your engineering capacity on infrastructure. Every hour spent configuring Helm charts is an hour not spent on product features that determine whether you have users to scale for.
  • For the growth from 1,000 to 100,000 DAU (a 100x increase): a single PostgreSQL instance with read replicas handles this comfortably. Add proper indexing, connection pooling (PgBouncer), and a CDN for static assets. Move expensive background work (email, report generation, image processing) to async workers (Celery + Redis or a managed queue like SQS). Implement caching at the application layer for frequently-read, rarely-changed data.
  • The architecture changes that actually matter at this stage: (1) Observability — add Prometheus/Grafana or Datadog so you know what is slow before users tell you. (2) CI/CD — every merge to main deploys automatically with rollback capability. (3) Horizontal scaling of the web tier — run 3-4 instances of the monolith behind a load balancer so you can handle traffic spikes and deploy without downtime.
  • The point at which microservices become worth discussing: when the team exceeds 15-20 engineers and distinct teams own distinct domains that need to deploy independently. That is probably at 500K+ DAU with product-market fit confirmed. For now, ship features fast and stay alive.
Follow-up: The CTO read a blog post about microservices and insists on breaking the monolith into 8 services before they even have product-market fit. How do you push back constructively?I would present it as a risk-return analysis, not a technology debate. “Microservices increase our time-to-market by 3-5x for a 5-person team because every feature now requires coordinating across services, managing distributed transactions, debugging network issues, and maintaining 8 deployment pipelines instead of 1. At our current stage, the biggest risk is not scaling — it is running out of runway before finding product-market fit. If we spend 6 months on infrastructure, we have 6 fewer months of product iteration.” I would show concrete examples: Shopify was a Rails monolith that scaled to billions in GMV. Basecamp runs a monolith with a small team. Stack Overflow serves millions of developers from a monolith. Then I would offer a compromise: “Let us structure the monolith with clean module boundaries (bounded contexts) using the SOLID principles we both value. When we hit a genuine scaling wall — and we will know because monitoring will tell us — we extract the specific module that is bottlenecked. This gives us the option to decompose later without paying the cost now.”