Interview Q&A Cicd All Levels

CI/CD Interview Questions & Answers

40+ CI/CD and DevOps interview questions covering pipelines, Jenkins, GitOps, deployment strategies, monitoring, and SRE — Basic to Advanced.

April 26, 2025 41 min read 37 Questions DB
37 Total Questions
5 Basic
16 Intermediate
16 Advanced
Level:
Q1
What is DevOps and why is it important?
Basic

Ans:

DevOps is a culture and set of practices that brings together software Development (Dev) and IT Operations (Ops) to shorten the development lifecycle and deliver high-quality software continuously.

Core principles:

  • Collaboration — Dev and Ops teams work together, not in silos
  • Automation — CI/CD, IaC, automated testing
  • Continuous feedback — monitoring, logging, observability
  • Continuous improvement — retrospectives, blameless post-mortems

Why it matters:

  • Faster releases (days vs months)
  • Higher quality (automated testing catches bugs early)
  • Lower failure rate (smaller, more frequent deployments)
  • Faster recovery (automation enables quick rollbacks)
Traditional: Dev writes code → hands off to Ops → Ops deploys → blame each other
DevOps: Dev + Ops collaborate → automate everything → deploy confidently daily
Q2
What are CI and CD? How are they different?
Basic

Ans:

TermFull NameWhat it does
CIContinuous IntegrationAutomatically builds and tests code when developers push changes
CDContinuous DeliveryAutomatically deploys to staging; manual gate for production
CDContinuous DeploymentFully automated — every passing build goes to production
Code push
    │
    ▼
CI: Build → Unit Tests → Integration Tests → Static Analysis
    │
    ▼
CD (Delivery): Deploy to Staging → Smoke Tests → [Manual Approval] → Production
                                                       ↑
                                                  (Delivery stops here)
CD (Deployment): Deploy to Staging → Tests → Automatically → Production

Key difference: Continuous Delivery requires a human to approve production deployment. Continuous Deployment does it automatically.

Q3
Explain the DevOps lifecycle.
Basic

Ans:

The DevOps lifecycle is an infinite loop of continuous improvement:

Plan → Code → Build → Test → Release → Deploy → Operate → Monitor
  ↑                                                            │
  └────────────────────────────────────────────────────────────┘
PhaseActivitiesTools
PlanSprint planning, backlogJira, Trello
CodeWrite code, code reviewGit, GitHub, GitLab
BuildCompile, packageMaven, Gradle, npm
TestUnit, integration, securityJUnit, Selenium, SonarQube
ReleaseArtifact managementNexus, JFrog Artifactory
DeployPush to environmentsAnsible, Kubernetes, Helm
OperateRun and manage infrastructureTerraform, Kubernetes
MonitorObserve, alert, feedbackPrometheus, Grafana, ELK
Q4
How does a CI/CD pipeline work? Explain with a real scenario.
Intermediate

Ans:

Real scenario: Node.js app deployed to Kubernetes

Developer pushes code to GitHub
          │
          ▼ (webhook triggers)
Jenkins/GitHub Actions
    │
    Stage 1: Checkout
    ├── git clone repo
    │
    Stage 2: Build
    ├── npm install
    ├── npm run build
    │
    Stage 3: Test
    ├── npm run test (unit tests)
    ├── npm run test:integration
    │
    Stage 4: Code Quality
    ├── SonarQube analysis
    ├── ESLint scan
    │
    Stage 5: Security Scan
    ├── trivy image scan
    ├── OWASP dependency check
    │
    Stage 6: Build & Push Docker Image
    ├── docker build -t myapp:${GIT_COMMIT_SHORT} .
    ├── docker push registry/myapp:${GIT_COMMIT_SHORT}
    │
    Stage 7: Deploy to Staging
    ├── helm upgrade --install myapp ./chart --set image.tag=${GIT_COMMIT_SHORT}
    ├── Wait for rollout
    ├── Run smoke tests
    │
    Stage 8: Manual Approval (for prod)
    ├── Notify Slack → team approves
    │
    Stage 9: Deploy to Production
    ├── helm upgrade myapp ./chart -n production --set image.tag=${GIT_COMMIT_SHORT}
    │
    Stage 10: Notify
    └── Slack/email notification with status
// Jenkinsfile example
pipeline {
  agent any
  stages {
    stage('Build') { steps { sh 'npm install && npm run build' } }
    stage('Test')  { steps { sh 'npm test' } }
    stage('Docker Build') {
      steps {
        sh "docker build -t myapp:${GIT_COMMIT[0..7]} ."
        sh "docker push myapp:${GIT_COMMIT[0..7]}"
      }
    }
    stage('Deploy Staging') {
      steps { sh "helm upgrade --install myapp ./chart --set image.tag=${GIT_COMMIT[0..7]}" }
    }
    stage('Prod Approval') {
      steps { input message: 'Deploy to production?', ok: 'Deploy' }
    }
    stage('Deploy Prod') {
      steps { sh "helm upgrade myapp ./chart -n prod --set image.tag=${GIT_COMMIT[0..7]}" }
    }
  }
}
Q5
What is blue-green deployment? When do you use it?
Intermediate

Ans:

Blue-Green runs two identical production environments. Traffic switches instantly from old (blue) to new (green) with zero downtime. Blue stays as instant rollback.

                    ┌─── Blue (v1) ←── traffic off
Load Balancer ──────┤
                    └─── Green (v2) ←── all traffic

Flow:

  1. Deploy v2 to Green environment (no user traffic yet)
  2. Run smoke tests on Green
  3. Switch load balancer: all traffic → Green
  4. Green is now “live production”
  5. Blue stays running (instant rollback capability)
  6. After confidence → decommission Blue or keep for next release
# Kubernetes Blue-Green with service selector switch
# Blue deployment: label app: myapp-blue
# Green deployment: label app: myapp-green

# Service points to blue:
kubectl patch service myapp -p '{"spec":{"selector":{"version":"blue"}}}'

# After green is ready and tested:
kubectl patch service myapp -p '{"spec":{"selector":{"version":"green"}}}'

# Rollback (instant):
kubectl patch service myapp -p '{"spec":{"selector":{"version":"blue"}}}'

When to use: Mission-critical apps where downtime is unacceptable. Requires 2x infrastructure cost.

Q6
What is canary deployment? When do you use it?
Intermediate

Ans:

Canary deployment gradually shifts a small percentage of traffic to the new version, monitoring for issues before full rollout.

v1 (stable) ←── 90% of users
v2 (canary) ←── 10% of users (canary group)

If no issues after 30 min → increase to 50% → 100%
If issues → route 100% back to v1
# Kubernetes Canary with nginx-ingress
# Stable service:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp-stable
spec:
  rules:
  - host: myapp.com
    http:
      paths:
      - backend:
          service:
            name: myapp-v1
            port:
              number: 80
---
# Canary ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp-canary
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "10"  # 10% traffic
spec:
  rules:
  - host: myapp.com
    http:
      paths:
      - backend:
          service:
            name: myapp-v2
            port:
              number: 80

When to use: Large-scale systems where you want risk-minimized rollouts with real user validation.

Blue-Green vs Canary:

  • Blue-Green: instant, full switch, high resource cost
  • Canary: gradual, lower risk, more complex, lower resource cost
Q7
Jenkins pipeline stuck at a stage — how do you troubleshoot?
Intermediate

Ans:

# Step 1: Check the console output
# Jenkins UI → Job → Build Number → Console Output

# Step 2: Look for timeout issues
# Stage hung on: sh script, ssh, API call?
# Add timeouts to stages:
stage('Deploy') {
  options { timeout(time: 10, unit: 'MINUTES') }
  steps { sh './deploy.sh' }
}

# Step 3: Check if it's waiting for input
# Jenkins UI → Pending Input Actions → Check for approval buttons

# Step 4: Check agent/node connectivity
# Jenkins → Manage Jenkins → Nodes → Check if agent is online

# Step 5: Check for hung processes on agent
ssh jenkins-agent
ps aux | grep <process-from-pipeline>
# Kill the hung process if needed

# Step 6: Check Jenkins system log
# Jenkins → Manage Jenkins → System Log → All Jenkins Logs

# Step 7: Check build workspace on agent
ls -la /var/lib/jenkins/workspace/<job-name>/

# Step 8: If waiting on external service (Nexus, K8s, AWS):
# - Check if the service is reachable
curl http://nexus:8081/nexus/
kubectl cluster-info

# Step 9: Kill the build if truly stuck
# Jenkins UI → Build → ⬛ (Stop)
# Or via CLI:
curl -X POST http://jenkins:8080/job/myjob/1/stop \
  --user admin:token
Q8
How do you optimize CI/CD pipeline performance?
Intermediate

Ans:

// 1. Run independent stages in parallel
stage('Parallel Tests') {
  parallel {
    stage('Unit Tests')        { steps { sh 'npm test' } }
    stage('Integration Tests') { steps { sh 'npm run test:integration' } }
    stage('Lint')              { steps { sh 'npm run lint' } }
  }
}

// 2. Cache dependencies
// Jenkins with Docker:
stage('Build') {
  steps {
    sh 'docker build --cache-from myapp:cache -t myapp:latest .'
  }
}

// 3. Shallow git clone (faster for large repos)
git url: 'https://github.com/org/repo.git', depth: 1

// 4. Use incremental builds
// Only rebuild if relevant files changed
when {
  changeset "src/**"
}

// 5. Use smaller/purpose-built agent images
// Agent with only needed tools, not a 3GB full-featured image

// 6. Artifact caching (Maven, npm, pip)
// ~/.m2, node_modules — mount as Docker volume or use cache action

// 7. Fail fast — run unit tests before expensive integration tests

// 8. Use build agents close to deployment targets (same AZ)
# Typical time breakdown:
# Slow pipeline: 45 min
# After parallel stages: 20 min
# After caching + shallow clone: 8 min
Q9
What is GitOps and how is it different from traditional CI/CD?
Intermediate

Ans:

GitOps is a practice where Git is the single source of truth for both application code AND infrastructure/deployment configuration. Changes to production happen only via Git commits.

Traditional CI/CD:            GitOps:
Code → CI → push → CD         Code → CI → Git commit → GitOps Agent → Cluster
(push model)                   (pull model — Flux/ArgoCD watches Git)
FeatureTraditional CI/CDGitOps
TriggerCI pipeline pushes to clusterAgent pulls from Git
SecretsIn CI/CD systemSealed Secrets or Vault
RollbackRe-run pipelinegit revert
AuditCI logsGit history
DriftCan drift unnoticedAgent continuously reconciles
ToolsJenkins, GitLab CIArgoCD, Flux

GitOps workflow with ArgoCD:

# 1. Developer pushes new image tag to values.yaml in gitops-repo
# 2. ArgoCD detects Git change (polls every 3 min or webhook)
# 3. ArgoCD compares Git state to cluster state
# 4. ArgoCD applies difference (deploys new version)
# 5. If someone manually changes cluster, ArgoCD reverts it

# Install ArgoCD
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# Create application
argocd app create myapp \
  --repo https://github.com/org/gitops-repo \
  --path apps/myapp \
  --dest-server https://kubernetes.default.svc \
  --dest-namespace production
Q10
How do you secure a CI/CD pipeline?
Intermediate

Ans:

Security layers:

1. Source Code Security
   - Branch protection rules (no direct push to main)
   - Required code reviews (at least 2 approvals)
   - Signed commits (GPG)
   - SAST: SonarQube, Semgrep, Checkmarx

2. Build Security
   - Use specific image tags (not :latest) for build agents
   - Pin dependency versions (package-lock.json, requirements.txt)
   - OWASP dependency check
   - Software Bill of Materials (SBOM) generation

3. Container Security
   - Trivy/Snyk scan before push
   - Non-root user in containers
   - Read-only filesystem
   - Sign images (Docker Content Trust / cosign + sigstore)
   - Use private registry (ECR, GCR, Nexus)

4. Secret Management
   - Never hardcode secrets in Jenkinsfile or .gitlab-ci.yml
   - Use Jenkins Credentials, GitHub Secrets, Vault
   - Rotate credentials regularly

5. Deployment Security
   - Least privilege IAM roles for CI/CD pipeline
   - Use OIDC (not long-lived access keys) for AWS
   - Network policies in Kubernetes
   - Audit log all deployments

6. Infrastructure
   - Run CI agents in isolated environments
   - Ephemeral build agents (spin up, use, terminate)
   - Separate deployment IAM roles per environment
# GitHub Actions OIDC (no AWS access keys needed)
- uses: aws-actions/configure-aws-credentials@v4
  with:
    role-to-assume: arn:aws:iam::123456789:role/GitHubActionsRole
    aws-region: us-east-1
Q11
Explain how Prometheus and Grafana work together.
Basic

Ans:

Application/Service
    │
    │ exposes /metrics endpoint (HTTP)
    ▼
Prometheus (scrapes /metrics every 15s, stores time-series data)
    │
    │ PromQL queries
    ▼
Grafana (connects to Prometheus as data source, visualizes dashboards)
    │
    ▼
Alertmanager (receives alerts from Prometheus rules, sends to Slack/PagerDuty)

Components:

ComponentRole
PrometheusPull-based metrics collector and time-series DB
ExportersExpose metrics: node_exporter (OS), kube-state-metrics (K8s), blackbox_exporter (HTTP)
AlertmanagerRoutes alerts to notification channels
GrafanaVisualization and dashboarding
# Default ports:
# Prometheus: 9090
# Grafana: 3000
# Alertmanager: 9093
# Node Exporter: 9100

# Example PromQL query in Grafana:
# CPU usage %:
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

# HTTP error rate:
rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m])
Q12
What is SRE and how is it different from DevOps?
Intermediate

Ans:

AspectDevOpsSRE
OriginCultural movement (collaboration)Engineering discipline (Google, 2003)
GoalFaster software deliveryReliability and scalability
FocusAutomation, CI/CDSLOs, SLAs, error budgets
TeamDev + Ops mergedDedicated reliability engineers
MetricsDeployment frequency, MTTRSLI/SLO/SLA, error budgets

SRE key concepts:

SLI (Service Level Indicator): Measurable metric (e.g., request latency p99)
SLO (Service Level Objective): Target (e.g., 99.9% requests < 500ms)
SLA (Service Level Agreement): Contract with consequences (e.g., 99.5% uptime or money back)
Error Budget: 100% - SLO = how much downtime you can "spend" (e.g., 0.1% = 43.8 min/month)
# SRE principle: if error budget is burned, stop feature releases
# and focus on reliability until budget recovers

# Error budget calculation:
# SLO: 99.9% → 0.1% budget → 43.8 minutes downtime allowed per month
# If we've used 40 minutes → only 3.8 min left → freeze risky deployments
Q13
What is observability and how is it different from monitoring?
Intermediate

Ans:

AspectMonitoringObservability
FocusKnown failure modesUnknown/unexpected failures
ApproachPre-defined dashboardsExplore and query freely
Answer“Is this component up?”“Why is this slow for these users?”
DataMetricsMetrics + Logs + Traces (the 3 pillars)

Three Pillars of Observability:

Metrics  → What is happening? (CPU=90%, error_rate=5%)
Logs     → What happened? (ERROR: connection refused to db:5432)
Traces   → Where is the bottleneck? (request took 3s, 2.5s in DB query)

Tools:

PillarOpen SourceCommercial
MetricsPrometheus, GrafanaDatadog, New Relic
LogsELK Stack, LokiSplunk, Datadog Logs
TracesJaeger, Zipkin, TempoDatadog APM, Honeycomb
# Distributed tracing example with OpenTelemetry
# Each service adds trace context to requests
# Jaeger UI shows: service A → service B (200ms) → service C (2.3s) ← bottleneck
Q14
How do you handle rollback in production?
Intermediate

Ans:

Strategy depends on deployment type:

# 1. Kubernetes rollback (fastest)
kubectl rollout undo deployment/myapp
kubectl rollout undo deployment/myapp --to-revision=3
kubectl rollout status deployment/myapp   # Monitor

# 2. Helm rollback
helm rollback myapp 3      # Roll back to revision 3
helm history myapp         # Show release history

# 3. Docker Swarm rollback
docker service rollback myapp

# 4. Blue-Green rollback
# Switch load balancer back to blue environment
aws elbv2 modify-listener \
  --listener-arn <arn> \
  --default-actions Type=forward,TargetGroupArn=<blue-tg-arn>

# 5. Database rollback (most complex)
# Run down-migration scripts
flyway repair
flyway migrate -target=V2__baseline
# OR restore from pre-deployment snapshot

# 6. Pipeline-level rollback
# Trigger previous successful deployment pipeline
# Jenkins: Build with parameters → pass old image tag

# 7. GitOps rollback
git revert <commit-hash>
git push   # ArgoCD auto-deploys previous version

Golden rule: Always test rollback procedure before it’s needed in a real incident.

Q15
How do you perform disaster recovery and backups in DevOps?
Advanced

Ans:

RTO and RPO:

RPO (Recovery Point Objective): How much data loss is acceptable? (e.g., max 1 hour)
RTO (Recovery Time Objective): How fast must you recover? (e.g., < 4 hours)

Backup strategy:

# Databases
# RDS automated backups (daily + transaction logs → point-in-time recovery)
aws rds modify-db-instance \
  --db-instance-identifier mydb \
  --backup-retention-period 7 \
  --preferred-backup-window "03:00-04:00"

# Manual snapshot before any major change
aws rds create-db-snapshot \
  --db-instance-identifier mydb \
  --db-snapshot-identifier pre-migration-snapshot

# EBS snapshots (automated with DLM)
aws dlm create-lifecycle-policy ...

# Application files → S3 (with versioning + cross-region replication)
aws s3api put-bucket-versioning --bucket myapp-data --versioning-configuration Status=Enabled

Disaster Recovery Tiers:

TierStrategyRTORPOCost
Backup & RestoreRestore from S3/snapshotsHoursHours$
Pilot LightCore services running in DR region~1 hourMinutes$$
Warm StandbyScaled-down replica always runningMinutesSeconds$$$
Multi-site Active-ActiveFull capacity in 2+ regionsSecondsNear-zero$$$$
# Test DR regularly:
# 1. Terminate primary DB → confirm failover to read replica
# 2. Restore snapshot to new instance
# 3. Failover Route 53 to DR region
# Document recovery runbooks and drill quarterly
Q16
How do you design logging and monitoring for a microservices architecture?
Advanced

Ans:

Each microservice → structured JSON logs → centralized collector → storage → query/alert

Architecture:
Microservices (stdout logs)
    │
Fluentd/Fluent Bit (DaemonSet in K8s) ← collects from all pods
    │
    ├──→ Elasticsearch/OpenSearch (search & store logs)
    │           ↓
    │        Kibana (visualize, search logs)
    │
    └──→ Loki (cost-efficient, Grafana-native)
                ↓
            Grafana (query with LogQL)

Structured logging (JSON) — crucial for filtering:

{
  "timestamp": "2024-01-01T10:00:00Z",
  "level": "ERROR",
  "service": "payment-api",
  "trace_id": "abc123",
  "user_id": "u-456",
  "message": "Payment gateway timeout",
  "duration_ms": 5001
}

Correlation across services (distributed tracing):

# Each request gets a unique trace_id
# Passed in HTTP headers: X-Trace-ID
# All services log it → you can search all logs for a single user request

# Jaeger/Zipkin shows the full call chain:
# API Gateway → Auth Service → Payment Service → Database

Alerting rules:

# Prometheus alert for high error rate
groups:
- name: microservices
  rules:
  - alert: HighErrorRate
    expr: rate(http_requests_total{status=~"5.."}[5m]) > 0.01
    for: 2m
    labels:
      severity: critical
    annotations:
      summary: "{{ $labels.service }} error rate > 1%"
Q17
How do you reduce MTTR (Mean Time To Recovery) in production systems?
Advanced

Ans:

MTTR = Detection time + Diagnosis time + Fix time + Verification time

# Reduce Detection Time:
# - Alerting thresholds tight enough to catch issues before users notice
# - Synthetic monitoring (ping endpoints every 30s from multiple regions)
# - Real User Monitoring (RUM) — detect impact immediately
# - On-call rotation with <5 min response SLA

# Reduce Diagnosis Time:
# - Runbooks for every alert (link in alert itself)
# - Pre-built dashboards per service
# - Distributed tracing (find bottleneck in seconds, not hours)
# - Structured logs with correlation IDs (grep single trace_id)

# Reduce Fix Time:
# - One-click rollback scripts ready
# - Feature flags (disable bad feature without redeploy)
# - Circuit breakers (auto-isolate failing service)
# - Pre-approved emergency changes

# Reduce Verification Time:
# - Smoke tests that run in < 2 minutes
# - Synthetic traffic patterns

# Cultural practices:
# - Blameless post-mortems → learn without fear
# - GameDays / Chaos Engineering (simulate failures safely)
# - Runbooks kept up-to-date and reviewed quarterly
Q18
Explain the Maven lifecycle.
Basic

Ans:

Maven has three built-in lifecycles. The most important is the default (build) lifecycle:

PhaseWhat happens
validateValidates project is correct and all info is available
compileCompiles source code (src/main/java)
testRuns unit tests (JUnit, TestNG)
packagePackages compiled code into JAR/WAR
verifyRuns integration tests, checks package quality
installInstalls package into local Maven repository (~/.m2)
deployDeploys to remote repository (Nexus, Artifactory)
# Run up to package phase:
mvn package

# Run up to install:
mvn install

# Skip tests:
mvn package -DskipTests

# Run specific phase:
mvn compile

# Clean previous build before build:
mvn clean package

Other lifecycles:

  • clean — removes target/ directory
  • site — generates project documentation
Q19
What is immutable vs mutable infrastructure?
Intermediate

Ans:

AspectMutable InfrastructureImmutable Infrastructure
UpdatesSSH in and patch the serverReplace old server with new pre-built image
DriftCommon (servers diverge over time)None (every server from same image)
DebuggingEasier (server is long-lived)Harder (must reproduce in new image)
RollbackManual, riskyFast (launch old AMI/image)
SnowflakesCommonPrevented
ToolsAnsible, Chef, PuppetPacker + Terraform, Docker + K8s

Immutable approach:

# 1. Build AMI with Packer (bake everything in)
packer build web-server.json
# Creates: ami-1234567890abcdef0

# 2. Terraform deploys instances from that AMI
resource "aws_launch_template" "web" {
  image_id      = "ami-1234567890abcdef0"
  instance_type = "t3.micro"
}

# 3. New version? Build new AMI, update Terraform, roll out
# Old AMI stays for rollback

Containers are inherently immutable — you never patch a running container; you build a new image and redeploy.

Q20
If there is an unexpected configuration change in AWS, how do you detect who made the change and when?
Intermediate

Ans:

# Method 1: AWS CloudTrail (primary audit tool)
# CloudTrail records every API call with: who, what, when, from where

# Search CloudTrail for recent changes
aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=ResourceName,AttributeValue=i-1234567890abcdef0 \
  --start-time 2024-01-01T00:00:00Z

# Query via CloudWatch Logs Insights (if CloudTrail → CloudWatch enabled):
fields userIdentity.arn, eventName, eventTime, requestParameters
| filter eventSource = "ec2.amazonaws.com"
| filter eventName = "ModifyInstanceAttribute"
| sort eventTime desc
| limit 20

# Method 2: AWS Config
# Tracks resource configuration history
aws configservice get-resource-config-history \
  --resource-type AWS::EC2::Instance \
  --resource-id i-1234567890abcdef0

# Method 3: AWS Config Rules + SNS
# Set up Config rule to detect unauthorized changes
# Alert via SNS → email/Slack

# Method 4: EventBridge (CloudWatch Events) → Lambda → Slack
# Rule: "When EC2 SecurityGroup is modified → trigger Lambda → post to Slack"

# Prevention:
# - Enable CloudTrail across all regions + all accounts (org trail)
# - Store CloudTrail logs in central immutable S3 bucket (MFA Delete enabled)
# - Set up Config conformance packs for compliance monitoring
Q21
Explain your end-to-end CI/CD pipeline architecture.
Advanced

Ans:

A production-grade pipeline architecture spans source control through multi-environment promotion, with quality gates at each hop:

Developer → Feature Branch → PR
    │
    ▼ (PR checks: lint, unit tests, SAST — fast feedback, < 5 min)
Merge to main
    │
    ▼
CI Stage (triggered by webhook)
  ├── Checkout + dependency install (cached)
  ├── Unit + integration tests (parallel)
  ├── SAST scan (SonarQube/Semgrep)
  ├── Build artifact (Docker image, versioned by commit SHA)
  ├── Container scan (Trivy) — block on CRITICAL
  └── Push to registry (ECR)
    │
    ▼
CD Stage — Environment Promotion
  Dev  (auto-deploy on every merge)
    │  smoke tests pass
    ▼
  Staging (auto-deploy, full regression + perf tests)
    │  manual approval gate
    ▼
  Production (canary 10% → monitor → 100%, or blue-green switch)
    │
    ▼
Post-deploy: smoke tests, notify Slack, tag release in Git

Key architectural principles:

  • Same artifact promoted through every environment — never rebuild between stages (eliminates “works in staging, breaks in prod”)
  • Fail fast — cheap checks (lint, unit tests) run before expensive ones (integration, deploy)
  • Immutable, versioned artifacts — image tags are commit SHAs, never :latest
  • Everything as code — the pipeline definition (Jenkinsfile/GitHub Actions YAML) and infrastructure (Terraform) both live in Git, reviewed via PR
  • Observability built in — every stage emits metrics/logs so a failed pipeline is diagnosable from the dashboard, not by re-running blindly
Q22
How do you secure secrets in a CI/CD pipeline?
Intermediate

Ans:

Secrets in a pipeline fall into two categories:
1. Secrets the PIPELINE needs (cloud credentials, registry tokens)
2. Secrets the APPLICATION needs (DB passwords, API keys) — passed through at deploy time

For pipeline credentials — eliminate long-lived secrets entirely:

# GitHub Actions: OIDC federation — no stored AWS keys at all
- uses: aws-actions/configure-aws-credentials@v4
  with:
    role-to-assume: arn:aws:iam::123456789:role/GitHubActionsRole
    aws-region: us-east-1

The IAM role trusts GitHub’s OIDC token issuer directly — nothing to leak, nothing to rotate.

For application secrets — never let them touch pipeline logs or source:

# Jenkins: injected via Credentials Manager, masked in console output
withCredentials([string(credentialsId: 'db-pass', variable: 'DB_PASS')]) {
  sh 'deploy.sh'   // $DB_PASS available in env, never printed
}

# Kubernetes deploys: pull from Secrets Manager at deploy time, not baked into image
aws secretsmanager get-secret-value --secret-id prod/db-password

Defense in depth:

  • Run gitleaks/trufflehog as a pre-commit hook AND a CI gate to catch accidental commits
  • Scope pipeline IAM roles to least privilege, per environment (dev pipeline role can’t touch prod)
  • Use ephemeral build agents — a compromised agent has nothing persistent to steal
  • Rotate any secret that’s ever appeared in a CI log, even if masked — treat exposure as compromise
Q23
Explain blue-green, rolling, and canary deployments with examples.
Intermediate

Ans:

All three solve the same problem — releasing a new version without downtime — with different risk/cost trade-offs:

StrategyHow it worksRollback speedInfra costRisk exposure
RollingReplace old Pods/instances with new ones gradually, a few at a timeSlow (must roll back gradually too)Low (no extra capacity)Medium — bad version reaches some users during rollout
Blue-GreenDeploy new version fully in parallel, then switch all traffic at onceInstant (switch back)High (2x capacity during cutover)Low — full validation before any real traffic hits it
CanaryRoute a small % of traffic to new version, increase gradually while monitoringFast (route back to 0%)Low-MediumLowest — issues caught with minimal blast radius
# Rolling update (Kubernetes default)
strategy:
  type: RollingUpdate
  rollingUpdate: { maxSurge: 1, maxUnavailable: 0 }

# Blue-Green: instant service selector switch
kubectl patch service myapp -p '{"spec":{"selector":{"version":"green"}}}'

# Canary: weighted traffic split via Ingress annotation
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "10"   # 10% to new version

When to use which:

  • Rolling — default choice for most stateless services; simple, no extra infra
  • Blue-Green — mission-critical apps where instant, tested cutover matters more than cost
  • Canary — high-traffic systems where you want real production signal before full rollout
Q24
Describe a production incident you handled and the lessons learned.
Advanced

Ans:

This is a behavioral question — interviewers want structure (STAR: Situation, Task, Action, Result), not just technical detail. Example answer:

Situation: During a flash sale, our checkout API started returning 500s for ~15% of requests. Alerts fired for elevated HTTPCode_Target_5XX_Count on the ALB and rising DatabaseConnections on RDS.

Task: As on-call engineer, I needed to restore checkout availability within our 15-minute incident SLA while identifying the root cause.

Action:

1. Checked CloudWatch dashboard — RDS connections were pinned at max_connections
2. Confirmed via app logs: "too many connections" errors from the DB driver
3. Immediate mitigation: bumped RDS max_connections and restarted the connection-pooling
   sidecar (PgBouncer) to clear stuck connections — checkout recovered within 6 minutes
4. Root cause: a recent deploy removed connection pool timeout config, so failed requests
   were leaking connections instead of releasing them back to the pool
5. Fix: restored the pool timeout config, added a CloudWatch alarm on connection
   utilization at 70% (well before exhaustion), and added a load test to the CI pipeline
   that specifically checks for connection leaks under sustained load

Result: Checkout was restored in 6 minutes; the permanent fix shipped the same day. We wrote a blameless post-mortem, and the new alarm + load test have caught two similar regressions in staging since, before they reached production.

What to emphasize when answering this yourself: calm, structured troubleshooting under pressure; distinguishing mitigation from root cause fix; and a concrete process/tooling change that prevents recurrence — not just “we fixed it.”

Q25
How did you reduce a pipeline from 1 hour to 20 minutes?
Advanced

Ans:

This is a “walk me through your optimization process” question — interviewers want the diagnostic method, not just the final tricks. Example structure:

1. Measure first — don’t guess:

// Add timestamps() to see exactly where time is going, stage by stage
options { timestamps() }

Baseline breakdown for a 60-minute pipeline:

Checkout (full clone):        6 min
npm install (no cache):      12 min
Unit tests (sequential):     15 min
Integration tests:           14 min
Docker build (no cache):     10 min
Deploy + smoke test:          3 min
                             ─────
Total:                       60 min

2. Attack the biggest offenders first:

// Shallow clone instead of full history → 6 min → 45 sec
git url: 'https://github.com/org/repo.git', depth: 1

// Cache dependencies between runs → 12 min → 2 min
// (mount ~/.npm or use actions/cache in GitHub Actions)

// Run unit + integration tests in parallel, not sequential → 29 min → 15 min
stage('Tests') {
  parallel {
    stage('Unit')        { steps { sh 'npm test' } }
    stage('Integration') { steps { sh 'npm run test:integration' } }
  }
}

// Docker layer caching → 10 min → 3 min
sh 'docker build --cache-from myapp:cache -t myapp:latest .'

3. Result:

Checkout (shallow):            1 min
npm install (cached):          2 min
Tests (parallel):             15 min
Docker build (cached):         3 min
Deploy + smoke test:           3 min
                               ─────
Total:                        ~20 min (67% reduction)

Key talking point: the win wasn’t one silver bullet — it was measuring first to find the actual bottlenecks (not assumed ones), then applying parallelism and caching specifically where the time was going. Also worth mentioning: this isn’t a one-time fix — add a pipeline duration metric to your dashboards so regressions get caught before they creep back to 60 minutes.

Q26
Your deployment pipeline succeeds, but the application fails after deployment. What would be your next steps?
Advanced

Ans:

A “green” pipeline only proves the deploy step succeeded (the new version reached the cluster/servers) — it says nothing about whether the application is actually healthy once running. Work through it methodically:

1. Don't panic-rollback immediately — spend 2 minutes confirming scope
   - Is EVERY instance/pod failing, or just some? (partial vs total failure)
   - Did it fail immediately, or after receiving real traffic?

2. Check the obvious first — application logs from the new version
   kubectl logs -l app=myapp --tail=100
   # or: journalctl -u myapp -n 100 --no-pager

3. Check what's DIFFERENT about this deploy vs the last working one
   - New environment variables / ConfigMap / Secret missing a key?
   - Database migration that hasn't run yet, or ran but broke a query?
   - A config value that's fine in staging but wrong for prod scale?

4. Check readiness/health endpoints directly
   curl -v http://<pod-ip>:8080/health

5. Compare with the previous version's config, side by side
   kubectl diff -f deployment.yaml
   # or diff the actual running ConfigMap/Secret against the previous revision

6. If root cause isn't obvious within your incident SLA — roll back FIRST,
   investigate AFTER. Restoring service takes priority over "understanding why."
   kubectl rollout undo deployment/myapp

Why this happens more often than it should: pipelines usually only test that the deploy mechanism worked (image pulled, pod started, kubectl apply succeeded) — not that the application is functionally correct with production config, data, and traffic. The fix going forward is adding a post-deploy smoke test stage to the pipeline itself (hit a few real endpoints, check a real health check, run a synthetic transaction) so “pipeline succeeded” and “application works” become the same claim instead of two separate ones.

Q27
How would you design a CI/CD pipeline with an automatic rollback strategy?
Advanced

Ans:

The key design principle: the pipeline itself must be able to detect failure post-deploy and act on it — automatic rollback means nobody has to notice and manually trigger it.

Deploy new version (canary: 10% traffic, or a parallel "green" environment)
    │
    ▼
Automated health gate (wait 3-5 min, then evaluate)
  ├── Error rate  > baseline + threshold?  → FAIL
  ├── p99 latency > baseline + threshold?  → FAIL
  ├── Synthetic smoke test fails?          → FAIL
  └── All green?                            → PASS
    │
    ├── PASS → promote to 100% traffic
    │
    └── FAIL → automatic rollback, no human required
# Example: GitHub Actions stage that gates on real metrics before proceeding
- name: Deploy canary
  run: kubectl apply -f canary-deployment.yaml

- name: Wait and evaluate health
  run: |
    sleep 300
    ERROR_RATE=$(curl -s "$PROMETHEUS_URL/api/v1/query?query=rate(http_requests_total{status=~'5..',version='canary'}[5m])" | jq '.data.result[0].value[1]')
    if (( $(echo "$ERROR_RATE > 0.01" | bc -l) )); then
      echo "Error rate too high — rolling back"
      kubectl rollout undo deployment/myapp
      exit 1
    fi

- name: Promote to 100%
  if: success()
  run: kubectl argo rollouts promote myapp

Tooling that does this natively (don’t hand-roll it if you don’t have to):

  • Argo Rollouts — canary/blue-green with automated analysis (AnalysisTemplate querying Prometheus) that auto-aborts and rolls back on threshold breach
  • Flagger — same idea, works with Istio/Linkerd/AWS App Mesh for traffic shifting + automated rollback
  • AWS CodeDeploy — built-in CloudWatch alarm-triggered automatic rollback for ECS/Lambda/EC2 deployments

Key interview point: automatic rollback requires a quantifiable health signal (error rate, latency, a synthetic check) evaluated automatically during a bake period — without that, “automatic rollback” is really just “fast manual rollback,” which is still valuable but not the same thing.

Q28
What would you do if your pipeline suddenly takes 30 minutes instead of 5?
Intermediate

Ans:

This is a regression diagnosis question — different from planned pipeline optimization, because something specific changed, and the job is finding what:

1. Check WHEN it started — correlate with a specific commit/merge, not just "recently"
   - Compare pipeline duration history: your CI system's build-time graph, or
     `git log` timestamps against your pipeline duration dashboard

2. Diff the recent commits for pipeline-relevant changes
   - New/changed dependency in package.json / requirements.txt / go.mod?
   - Someone modified the Jenkinsfile/workflow YAML itself (removed caching,
     removed parallelism, added a new sequential stage)?
   - A new, heavier test suite added without marking it as parallel?

3. Check external/environmental factors, not just your own code
   - Is the CI runner/agent pool overloaded (shared agents, another team's
     pipelines competing for the same runners)?
   - Registry pull speed degraded (base image got bigger, or registry is slow)?
   - Cache actually being hit, or silently invalidated (e.g., cache key
     changed because a lockfile hash changed unexpectedly)?

4. Add timestamps and compare stage-by-stage against the last known-good run
   options { timestamps() }   // Jenkins
   # or check the per-step duration breakdown GitHub Actions already shows

5. Isolate: re-run just the suspect stage in isolation to confirm the theory

Most common real-world causes, ranked by frequency: the build/test cache silently stopped hitting (often from a lockfile or Docker layer change invalidating it), a new dependency was added that’s slow to install, or the CI runner pool got smaller/busier (noisy neighbor problem on shared infrastructure) — rarely is it “the code got 6x more complex overnight.”

Q29
Production is down, and multiple teams join the incident bridge. How would you handle the situation?
Advanced

Ans:

With multiple teams on a bridge, the biggest risk isn’t lack of expertise — it’s chaos: everyone debugging in parallel, nobody coordinating, and changes happening without anyone tracking what was tried. Structure fixes this:

1. Establish an Incident Commander (IC) IMMEDIATELY — even before root cause is known
   - IC's job: coordinate, NOT debug. They don't touch the keyboard.
   - IC decides who investigates what, avoids 5 people SSH'd into the same
     box making conflicting changes simultaneously

2. Open a single source of truth — a dedicated incident channel/doc
   - Every finding, every action taken, every hypothesis — logged there,
     not scattered across DMs and verbal bridge chatter that nobody wrote down

3. Assign clear roles
   - IC: coordinates, makes the call on rollback/mitigation decisions
   - Comms lead: updates stakeholders/status page on a cadence (e.g., every 15 min),
     so engineers aren't interrupted to answer "any update?"
   - Subject-matter investigators: each team investigates their own service,
     reports findings back to the IC, doesn't unilaterally deploy fixes

4. Mitigate before you fully understand — restoring service beats
   understanding root cause under time pressure
   - Rollback the most recent deploy first (most common cause) unless there's
     clear evidence otherwise
   - Feature-flag off the suspect functionality if rollback isn't clean

5. Declare "all clear" explicitly, then schedule the blameless post-mortem
   - Don't do deep RCA ON the bridge — stabilize first, analyze after

What separates a strong answer here: naming the Incident Commander role specifically, and the point that the IC coordinates rather than debugs — many candidates describe good technical steps but skip the coordination structure, which is what actually breaks down when 4 teams join a bridge without one.

Q30
How do you perform a Root Cause Analysis (RCA) after a major production incident?
Advanced

Ans:

A good RCA process separates what happened (facts) from why it happened (root cause) from what changes (action items) — skipping straight to blame or to a shallow fix is the most common failure mode:

1. Build a factual timeline FIRST, before any analysis
   - When did the issue start (first alert / first user impact)?
   - When was it detected? When mitigated? When fully resolved?
   - What changed right before it started (deploys, config changes, traffic
     patterns, infrastructure events)? Pull this from CI/CD history, not memory.

2. Find the root cause, not just the trigger — ask "why" repeatedly (5 Whys)
   Example:
   "Checkout API returned 500s"
     → Why? "Database connection pool exhausted"
       → Why? "Connections weren't being released"
         → Why? "A recent deploy removed the connection timeout config"
           → Why? "Config change wasn't covered by a test or code review checklist"
   ← THIS is the actual root cause — not "the database ran out of connections"

3. Write it up in a BLAMELESS format
   - Focus on "what allowed this to happen" (process/system gaps),
     never "who caused this" — blame makes people hide problems next time
   - Include: summary, timeline, impact (user-facing + duration), root cause,
     what went well, what went poorly, and concrete action items

4. Action items must be SPECIFIC and ASSIGNED — not vague
   - Bad: "Improve monitoring"
   - Good: "Add a CloudWatch alarm on RDS connection pool utilization at 70%,
     owned by @platform-team, done by <date>"

5. Track action items to actual completion
   - An RCA whose action items never get done just repeats the incident later

Key interview point: the value of an RCA isn’t the document — it’s whether the same incident can happen again. A strong answer emphasizes blameless culture (so people report honestly) and specific, owned, tracked action items over a long narrative nobody reads twice.

Q31
How do you ensure that developers cannot commit unencrypted passwords or secrets into your Git repository before the code even hits the remote branch?
Intermediate

Ans:

The goal is to catch secrets locally, before git push — a CI-side scan (covered in an earlier question) is still a necessary backstop, but by then the secret has already left the developer’s machine and may be in local git history other people can see.

1. Install a pre-commit hook that blocks the commit itself:

# Using the `pre-commit` framework (language-agnostic, most common approach)
pip install pre-commit

# .pre-commit-config.yaml — checked into the repo, so it applies to everyone
cat <<'EOF' > .pre-commit-config.yaml
repos:
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.18.0
    hooks:
      - id: gitleaks
EOF

pre-commit install   # wires it into .git/hooks/pre-commit for this clone
# Now any attempt to commit a secret is blocked locally, before it's even
# staged into history:
git commit -m "add db config"
# ✗ gitleaks....................................................Failed
# Secret detected: AWS Access Key in config.py:14

2. Enforce it’s actually installed — don’t rely on developers remembering:

# Option A: a repo-level setup script every dev runs once when cloning
# Option B (stronger): enforce it server-side too, since a local hook
# can be bypassed with `git commit --no-verify`

3. Server-side backstop — GitHub push protection / pre-receive hook:

GitHub: Settings → Code security → Push protection
  → blocks the PUSH itself if a recognized secret pattern is detected,
    even if the developer skipped or never installed the local hook

Self-hosted Git (GitLab/Bitbucket Server): a pre-receive hook running
  gitleaks/trufflehog against the incoming commits, rejecting the push
  server-side — this is the one layer a developer literally cannot bypass

Layering, in order of when each catches the problem:

Local pre-commit hook (fastest feedback, but bypassable with --no-verify)
        │
Server-side push protection / pre-receive hook (can't be bypassed client-side)
        │
CI pipeline secret scan (final backstop — catches anything that slipped through)

Key interview point: a local pre-commit hook alone isn’t sufficient because --no-verify bypasses it trivially — the real guarantee comes from the server-side layer (GitHub push protection or a pre-receive hook), which the developer’s local git config can’t opt out of. Local hooks are still valuable for fast feedback; they’re just not the enforcement boundary.

Q32
How would you approach migrating a monolithic application to a microservices architecture? What steps would you follow, and what key challenges might you encounter during the migration process?
Advanced

Ans:

The biggest mistake teams make is a “big bang” rewrite — the safer, proven approach is incremental, using the Strangler Fig pattern: gradually route traffic away from the monolith one capability at a time, until nothing is left.

Steps:

1. Identify seams — find bounded contexts within the monolith
   (e.g., "orders", "payments", "inventory") using domain-driven design.
   Look for modules with minimal coupling to the rest of the codebase first.

2. Stand up a routing layer in front of the monolith (API Gateway / reverse proxy)
   Client → API Gateway → [monolith for most routes, new service for migrated ones]

3. Extract ONE service at a time, starting with the lowest-risk, most
   isolated capability — not the most "interesting" one
   - Build the new service, give it its own datastore if data can be separated
   - Gateway routes that specific path to the new service instead of the monolith
   - Keep the monolith's old code path as a rollback option initially

4. Handle data — usually the hardest part
   - Dual-write or CDC (Change Data Capture) to keep monolith DB and new
     service DB in sync during the transition window
   - Only fully cut over once the new service is proven stable in production

5. Repeat, service by service, until the monolith has nothing left to do
   — at which point it's decommissioned, not "rewritten"

Key challenges:

ChallengeWhy it’s hard
Data consistencySplitting a single ACID database into per-service databases introduces distributed transactions / eventual consistency where there used to be none
Distributed tracingA single request now spans multiple services — debugging requires correlation IDs and tools like Jaeger from day one, not added later
Network reliabilityIn-process function calls become network calls — need retries, circuit breakers, timeouts that didn’t exist before
Operational complexityGoing from 1 deployable to N means N CI/CD pipelines, N sets of logs/metrics/dashboards, N services to keep patched
Org/team boundariesServices work best when they map to team ownership (Conway’s Law) — splitting the code without splitting team ownership just creates a “distributed monolith”
TestingEnd-to-end tests get much harder to write and slower to run across service boundaries

Key interview point: emphasize the Strangler Fig approach and the fact that migration is driven by business capability boundaries, not arbitrary code splitting — and that a “distributed monolith” (many services, still tightly coupled and deployed together) is a common failure mode when teams extract services without also decoupling their data and their release cadence.

Q33
After deploying an application, it becomes slow. How would you troubleshoot the issue and rectify it?
Advanced

Ans:

“Slow” (not “down”) narrows the investigation — the app is functioning, so this is almost always a resource, dependency, or configuration regression introduced by the deploy itself:

1. Confirm it's actually deploy-related, not a coincidental traffic spike
   - Overlay the deploy timestamp on your latency/throughput dashboard
   - Check if traffic volume also changed at the same time (correlation ≠ causation)

2. Compare resource usage: new version vs old
   kubectl top pods -l app=myapp          # CPU/memory per pod, new vs old version
   - New code doing more work per request? (N+1 queries, missing cache,
     synchronous call to something that used to be async)

3. Check what actually CHANGED in this deploy
   git diff <previous-tag> <current-tag> --stat
   - New dependency added? New synchronous external API call?
   - Database migration that dropped an index or changed a query plan?

4. Check the database — the most common real culprit for "app got slow"
   - New query without an index (fast in dev with 100 rows, slow in prod with 10M)
   - Connection pool exhausted due to a leak in the new code
   EXPLAIN ANALYZE <the slow query>;   # look for seq scans where an index should be used

5. Check downstream dependencies — did THIS deploy start calling a
   slower external service, or increase call volume to an existing one?

6. Check for resource limit changes — did the new Deployment spec
   accidentally ship with lower CPU/memory requests than before?
   kubectl get deployment myapp -o jsonpath='{.spec.template.spec.containers[0].resources}'

Rectify:

Immediate: if root cause isn't obvious fast, roll back first — restore
  performance, investigate the "why" without users still suffering

Root-cause fix: add the missing index / fix the N+1 query / add caching /
  fix the resource limits — then re-deploy with a load test gate this time

Prevent recurrence: add automated performance regression testing to the
  pipeline (compare p95 latency of a canary against baseline before
  promoting to 100% traffic) so this is caught before users see it

Most common real-world root cause, by far: a database query that was fine against a small dev/staging dataset but scans a full table in production — this is why load testing against production-scale data (or at least production-scale query plans) before a deploy catches far more issues than load testing against a toy dataset.

Q34
Do you maintain a single CI/CD pipeline for all environments (Development, SIT, UAT, and Production), or do you use separate pipelines? How do you manage environment-specific configurations and deployments?
Advanced

Ans:

One pipeline definition, promoted through environment stages is the industry-standard approach — not separate pipeline definitions per environment. The reasoning: you want to prove the exact same artifact and the exact same deployment logic works identically everywhere, just with different config values and gates.

ONE pipeline (Jenkinsfile / workflow.yml), stages promote through environments:

Build once → produce ONE versioned artifact (image:sha123)
    │
    ▼
Deploy to Dev (auto, on every merge)
    │
    ▼
Deploy to SIT (auto, runs integration test suite)
    │
    ▼
Deploy to UAT (manual approval gate — business/QA sign-off)
    │
    ▼
Deploy to Production (manual approval gate + canary/rolling strategy)

Why NOT separate pipelines per environment:

  • Duplicated pipeline logic drifts over time (someone fixes a bug in the prod pipeline, forgets to port it to UAT’s copy)
  • You’d be testing a DIFFERENT build process per environment — defeats the purpose of “what passed staging is exactly what ships to prod”

Managing environment-specific configuration — never bake it into the artifact, inject it at deploy time:

# Kubernetes: separate values files per environment, same Helm chart
helm upgrade myapp ./chart -f values-dev.yaml    -n dev
helm upgrade myapp ./chart -f values-sit.yaml    -n sit
helm upgrade myapp ./chart -f values-uat.yaml    -n uat
helm upgrade myapp ./chart -f values-prod.yaml   -n prod
# Same chart, same image tag — only the values file (replicas, resource
# limits, external endpoints, feature flags) differs per environment
# Secrets: never in the values files themselves — pulled per-environment
# from Secrets Manager/SSM at deploy time, scoped by environment path
aws secretsmanager get-secret-value --secret-id /prod/myapp/db-password
aws secretsmanager get-secret-value --secret-id /uat/myapp/db-password

Gates differ per environment, even though the pipeline is one: Dev might auto-deploy with zero gates; UAT requires a QA sign-off; Production requires a change-approval gate plus a canary/rolling strategy with automated rollback. The pipeline code is shared — the policy (approvals, config, deployment strategy) is what varies per stage.

Q35
Your CI/CD pipeline works in staging but fails in production with 'permission denied' — how do you debug?
Advanced

Ans:

If the exact same pipeline logic works in one environment and not another, the difference is almost always IAM/credentials scope or file-system permissions specific to that environment — not the pipeline code itself:

# 1. Confirm WHICH operation is actually failing — read the error precisely
#    "permission denied" from AWS CLI, kubectl, or the OS shell are all
#    different problems with different fixes
# AWS API call → IAM issue
# kubectl command → Kubernetes RBAC issue
# File write → OS file permission issue

# 2. If it's an AWS API call — compare the IAM role/policy the pipeline
#    assumes in staging vs. production (often deliberately more restrictive in prod!)
aws iam get-role-policy --role-name prod-deploy-role --policy-name deploy-policy
aws iam simulate-principal-policy \
  --policy-source-arn arn:aws:iam::PROD_ACCOUNT:role/prod-deploy-role \
  --action-names s3:PutObject --resource-arns arn:aws:s3:::prod-bucket/*

# 3. If it's kubectl — check the RBAC binding for the pipeline's service account
#    in the PRODUCTION cluster specifically (often narrower than staging's, by design)
kubectl auth can-i create deployments --as=system:serviceaccount:ci:pipeline-sa -n production

# 4. If it's a file-system operation — check ownership/permissions differences
#    between staging and prod hosts (different deploy user, different umask)
ls -la /opt/app/  # on the prod target, compare against staging

# 5. Check for a DIFFERENT credential source entirely between environments
#    (e.g., staging uses long-lived keys that happen to be over-privileged;
#    prod correctly uses a scoped OIDC role — the "bug" is actually staging
#    being misconfigured, not production)

Most common root cause: production IAM roles/RBAC are (correctly) scoped more tightly than staging’s, and the pipeline is trying to do something — write to a specific bucket path, create a specific resource type — that was never explicitly granted in the production policy because nobody needed it there before. The fix is almost always adding the specific missing permission to the prod role, not widening it broadly to match staging.

Important distinction to raise in an interview: this is often correct behavior, not a bug — if staging’s permissions are looser than production’s by design, “it works in staging” doesn’t mean “it should work in production” without deliberately granting that permission. Investigate before assuming prod’s tighter policy is wrong.

Q36
What is error budget and burn rate in SRE?
Advanced

Ans:

Error budget (covered in more detail in an earlier question) is simply 100% - SLO — the amount of unreliability you’re allowed to “spend” in a given window before you’ve broken your promise to users. Burn rate is a different, complementary concept: it measures how fast you’re consuming that budget right now, which is what actually triggers a page — not the raw error count.

SLO: 99.9% availability over 30 days
Error budget: 0.1% = 43.2 minutes of allowed downtime per 30 days

Burn rate = (actual error rate) / (error rate allowed by the SLO)

Burn rate of 1x  = consuming budget exactly as fast as "planned" —
                    if this continues all month, you land exactly at the SLO
Burn rate of 10x = consuming budget 10x faster than planned —
                    at this rate, you'll exhaust the ENTIRE month's budget in ~3 days
Burn rate of 100x = exhausting the month's budget in under 7 hours

Why burn rate matters more than a raw threshold alert: a single short 5xx spike might burn 2% of your monthly budget in 5 minutes — that’s a 10x+ burn rate and worth paging on immediately, even though the absolute error COUNT looks small. Conversely, a low-grade elevated error rate that’s still within a 1x burn doesn’t need to wake anyone at 3 AM — it’ll self-resolve within the budget over the month.

# Multi-window, multi-burn-rate alert (the pattern Google's SRE book
# recommends) — page urgently on FAST burn, ticket on SLOW burn
groups:
- name: error-budget-burn
  rules:
  - alert: ErrorBudgetBurnFast
    expr: |
      (sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m]))) > (14.4 * 0.001)
      and
      (sum(rate(http_requests_total{status=~"5.."}[1h])) / sum(rate(http_requests_total[1h]))) > (14.4 * 0.001)
    labels: { severity: page }
    annotations: { summary: "Burning error budget 14.4x too fast — will exhaust in 2 days at this rate" }

  - alert: ErrorBudgetBurnSlow
    expr: |
      (sum(rate(http_requests_total{status=~"5.."}[6h])) / sum(rate(http_requests_total[6h]))) > (3 * 0.001)
    labels: { severity: ticket }
    annotations: { summary: "Burning error budget 3x too fast — investigate this week, not tonight" }

Interview one-liner: “Error budget tells you how much unreliability you can afford; burn rate tells you whether you’re about to run out of it soon enough to matter — and that’s the number that should actually decide whether someone gets paged at 3 AM.”

Q37
What is Platform Engineering and how would you design an IDP (Internal Developer Platform)?
Advanced

Ans:

Platform Engineering is the discipline of building internal tooling and self-service infrastructure so application teams can ship software without needing deep Kubernetes/Terraform/cloud expertise themselves — the platform team’s “customers” are the org’s own developers, and the product is a paved road, not a specific app.

Why it emerged: as infra grew more powerful (Kubernetes, service mesh, multi-cloud), it also grew far more complex — expecting every app team to become Kubernetes experts just to ship a service doesn’t scale. An IDP (Internal Developer Platform) is the concrete product platform engineering builds to solve this.

Core IDP design:

Developer                                Platform (what you're designing)
    │                                            │
    │  1. Self-service portal / CLI              │
    ├──────────────────────────────────────────► │  (Backstage, or a custom CLI)
    │     "give me a new service, with a         │
    │      database, CI/CD, and a dashboard"     │
    │                                            │
    │  2. Golden path templates                  │
    │ ◄────────────────────────────────────────  │  (Cookiecutter/Backstage templates:
    │     Pre-wired repo: Dockerfile, CI          │   pre-approved patterns, not a blank slate)
    │     pipeline, base K8s manifests, IAM       │
    │     role — all following org standards      │
    │                                            │
    │  3. Deploys via the SAME golden path        │
    ├──────────────────────────────────────────► │  (GitOps — ArgoCD applies what the
    │                                            │   template generated, consistently)
    │                                            │
    │  4. Observability included by default       │
    │ ◄────────────────────────────────────────  │  (dashboards, logs, traces auto-wired —
                                                     developer didn't have to configure this)

Key components to mention:

ComponentPurpose
Service catalog (e.g., Backstage)Discoverability — every team can see what services exist, who owns them, their docs
Golden path templatesOpinionated, pre-approved scaffolding — reduces decisions developers have to make correctly
Self-service provisioningA database, a namespace, a new service — requested via portal/CLI/PR, not a ticket to the platform team
GitOps deployment layerConsistent, auditable delivery mechanism underneath every golden path
Built-in observability/guardrailsSecurity scanning, cost tagging, logging/metrics wired in automatically, not opt-in

Key interview point — the platform is a PRODUCT, not a project: the platform team should treat internal developers as customers, measure adoption/satisfaction, and make the golden path so genuinely easier than going around it that developers choose it voluntarily — a mandated-but-painful platform gets bypassed, an internal platform’s job isn’t just “provide infrastructure,” it’s to make the right way to do things also the easiest way.

Add More Questions to This Guide

Know a question that should be here? Share it and help the community!

Open Google Form