Lesson 32 of 49 advanced

Deployment & DevOps

From Code to Production

Open interactive version (quiz + challenge)

Real-world analogy

Writing code is like building a rocket in your garage. Deployment is launching it into orbit — you need a launchpad (server), enough fuel for the journey (scaling), a pre-flight checklist that never changes (CI/CD), and mission control watching every sensor (monitoring)!

What is it?

Deployment is the process of getting your code from your laptop to a server where users can access it. DevOps practices (CI/CD, containers, monitoring) make this reliable, repeatable, and automated.

Real-world relevance

Netflix deploys thousands of times per day. Amazon deploys every 11.7 seconds. Modern CI/CD pipelines make this possible — push code, let the robots handle the rest.

Key points

Code example

# 1. GitHub Actions CI/CD 🤖
# .github/workflows/deploy.yml
name: Deploy
on:
  push:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 20 }
      - run: pnpm install
      - run: pnpm test
      - run: pnpm build

  deploy:
    needs: test  # Only deploy if tests pass!
    runs-on: ubuntu-latest
    steps:
      - run: docker build -t myapp .
      - run: docker push myregistry/myapp
      - run: ssh server "docker pull && docker compose up -d"

# 2. Environment variables — never hardcode secrets! 🔐
# .env (NEVER commit this file!)
DATABASE_URL=mongodb://localhost:27017/myapp
JWT_SECRET=super-secret-key-change-in-production
REDIS_URL=redis://localhost:6379

// In NestJS — read env vars safely:
@Injectable()
export class AppConfigService {
  get databaseUrl(): string {
    return process.env.DATABASE_URL;
  }
}

// 3. Health check endpoint — monitoring calls this 🏥
@Controller('health')
export class HealthController {
  @Get()
  check() {
    return {
      status: 'ok',
      timestamp: new Date().toISOString(),
      uptime: process.uptime(),
      memory: process.memoryUsage(),
    };
  }
}

Line-by-line walkthrough

  1. 1. 1. GitHub Actions CI/CD 🤖
  2. 2. .github/workflows/deploy.yml
  3. 3.
  4. 4.
  5. 5.
  6. 6.
  7. 7.
  8. 8.
  9. 9.
  10. 10.
  11. 11.
  12. 12.
  13. 13.
  14. 14.
  15. 15.
  16. 16.
  17. 17.
  18. 18.
  19. 19.
  20. 20.
  21. 21.
  22. 22.
  23. 23.
  24. 24.
  25. 25.
  26. 26.
  27. 27. 2. Environment variables — never hardcode secrets! 🔐
  28. 28. .env (NEVER commit this file!)
  29. 29.
  30. 30.
  31. 31.
  32. 32.
  33. 33. In NestJS:
  34. 34. Decorator that adds metadata or behavior
  35. 35. Exporting for use in other files
  36. 36.
  37. 37. Returning a value
  38. 38. Closing block
  39. 39. Closing block
  40. 40.
  41. 41. 3. Health check endpoint 🏥
  42. 42. Decorator that adds metadata or behavior
  43. 43. Exporting for use in other files
  44. 44. Decorator that adds metadata or behavior
  45. 45.
  46. 46. Returning a value
  47. 47.
  48. 48.
  49. 49.
  50. 50.
  51. 51. Closing block
  52. 52. Closing block
  53. 53. Closing block

Spot the bug

const app = await NestFactory.create(AppModule);
app.listen(3000);
console.log("Running on port 3000");
Need a hint?
Should the port be hardcoded? And is app.listen being awaited?
Show answer
Two issues: 1) Port is hardcoded instead of using process.env.PORT || 3000. 2) app.listen() should be awaited. Fix: await app.listen(process.env.PORT || 3000);

Explain like I'm 5

Writing code is like building a paper airplane at your desk. Deployment is launching a real airplane! You need an airport (server), extra planes if lots of people want to fly (scaling), a checklist the pilot follows every single time (CI/CD), and a control tower watching the sky (monitoring). Going from 'I made a paper plane' to 'I fly passengers across the world!'

Fun fact

Amazon's deployment system handles over 150 million deployments per year. That's about 285 deployments per MINUTE! And you thought pushing to main was stressful... 😅

Hands-on challenge

Design a CI/CD pipeline with 3 stages: (1) Lint + Type-check (fail fast on code quality), (2) Unit tests + Integration tests in parallel, (3) Build Docker image and deploy to staging — but ONLY on the main branch. Add a Slack notification that reports whether the pipeline passed or failed. Draw the pipeline as a flowchart first!

More resources

Open interactive version (quiz + challenge) ← Back to course: Full-Stack Playbook