How to use this lesson
Cloud questions test whether you can pick the right level of abstraction (VMs → containers → serverless), and operate it securely:
- IAM roles, not keys;
- autoscaling with health checks;
- managed observability.
AWS is used as the example, but the concepts map to GCP and Azure.
Q1. What's the difference between EC2, ECS and Lambda? What are EKS and Fargate?
Short answer:
- EC2: virtual machines. Full control of the OS and runtime. You manage patching, scaling (Auto Scaling Groups) and deployment. It's good for legacy or custom workloads, or special hardware (GPUs).
- ECS (Elastic Container Service): AWS's container orchestrator. You define task definitions (the container, CPU and memory, IAM role) and services (desired count, load balancer integration, rolling or blue-green deployments). It's simpler than Kubernetes, and deeply AWS-integrated.
- EKS (Elastic Kubernetes Service): managed Kubernetes control plane. You get the Kubernetes API and ecosystem (Helm, Argo CD, operators), and portability, at the cost of more operational complexity than ECS.
- Fargate: a serverless compute engine for ECS or EKS. It runs containers without managing EC2 nodes, and is billed per vCPU and memory per second. There's less operational work, with some limits (no daemonsets on EKS Fargate, no GPUs, higher unit cost).
- Lambda: functions as a service. Event-driven, scales to zero, billed per request and duration, with a 15-minute maximum and limited memory and CPU. It's good for glue code, event processing and spiky or low traffic. Java's cold starts are mitigated with SnapStart, GraalVM native images (custom runtime), or Spring Cloud Function.
Rule of thumb: long-running Spring Boot services go on ECS/Fargate or EKS. Event handlers and cron-like jobs go on Lambda. EC2 is for special needs.
Short answer:
- Build an immutable artifact: a JAR (or container), stored in S3 or a registry. Better still, bake an AMI (Packer) with the JRE and application, or use user data or SSM to fetch it at boot.
- Run it as a service: a systemd unit (
ExecStart=/usr/bin/java -XX:MaxRAMPercentage=75 -jar /opt/app/app.jar, Restart=always, a dedicated user), with logs to the journal or CloudWatch agent.
- Configuration: environment variables from SSM Parameter Store or Secrets Manager (Spring Cloud AWS
spring.config.import=aws-parameterstore:/aws-secretsmanager:), with no credentials on disk. The instance profile (IAM role) grants access.
- Networking: private subnets, an ALB in front, security groups allowing only the ALB, and ALB health checks on
/actuator/health/readiness.
- Scaling and availability: an Auto Scaling Group across availability zones, with a launch template, health checks and instance refresh for deployments.
- Observability: the CloudWatch agent (logs, metrics), or OpenTelemetry → CloudWatch or X-Ray.
Also consider: Elastic Beanstalk (managed), or containers on ECS, for less undifferentiated heavy lifting.
Q3. How do you autoscale EC2 instances with load? What's the difference between Auto Scaling Groups and ECS scaling policies? What is autoscaling in general?
Short answer:
-
Autoscaling automatically adds or removes capacity to match demand, to keep performance SLOs at the lowest cost. It's driven by metrics (CPU, requests, queue depth), schedules, or predictions. It needs stateless instances, fast and healthy startup, and load balancer integration.
-
EC2 Auto Scaling Groups (ASG): scale the instances with policies:
- target tracking (for example, keep average CPU at 60%, or ALB requests per target at 1,000);
- step scaling;
- scheduled scaling (known peaks);
- predictive scaling.
Use health checks (EC2 plus ELB), warm pools, instance refresh, and mixed instance types or Spot instances for cost.
-
ECS Service Auto Scaling: scales the task count (containers) through Application Auto Scaling, with target tracking on service CPU or memory or ALB request count, or custom CloudWatch metrics (SQS depth). The underlying capacity comes from Fargate (no nodes to scale), or from EC2 capacity providers, whose managed scaling grows the ASG to fit the tasks.
-
In short: ASGs scale machines. ECS policies scale application copies. With EC2-backed ECS, you need both (linked by capacity providers). With Fargate, only the task scaling.
-
Tips: scale on the metric closest to the user experience (requests or latency), use cooldowns and stabilisation, set minimums for availability, and pre-scale before events (JVM warm-up takes time).
Q4. What's the difference between IAM roles and IAM policies?
Short answer:
- Policy: a JSON document of permissions:
Effect, Action, Resource, Condition. It defines what is allowed or denied (for example, s3:GetObject on arn:aws:s3:::invoices/*). There are managed and inline policies. Resource-based policies attach to the resources (bucket policies, KMS key policies). Permission boundaries and SCPs cap the permissions.
- Role: an identity with attached policies, assumed by trusted principals (EC2 instances through an instance profile, ECS tasks through the task role, Lambda, EKS pods through IRSA or Pod Identity, users through SSO, other accounts). It gives temporary credentials through STS, with no long-lived keys. Its trust policy defines who can assume it.
The best practice: one role per workload, with least-privilege policies, conditions (source VPC, tags), and no access keys in the application or environment.
Q5. How do you use AWS Secrets Manager with Spring Boot?
Short answer:
- Spring Cloud AWS (3.x):
spring.config.import=aws-secretsmanager:/prod/orders/db. The secret's JSON keys become properties (spring.datasource.username/password, mapped by name, or through property prefixes). Parameter Store works the same way (aws-parameterstore:).
- Credentials: the IAM role of the task, pod or instance, with
secretsmanager:GetSecretValue on the specific ARNs (and kms:Decrypt).
- Rotation: enable Secrets Manager rotation (built in for RDS). Applications must pick up the new credentials: restart or reload, or use the AWS JDBC wrapper or Secrets Manager JDBC driver, which re-fetch the credentials on authentication failure.
- Alternatives: inject them at deployment time (ECS task definition
secrets referencing ARNs, EKS External Secrets or CSI driver), so the application just reads environment variables or files.
- Cache the secret values (the SDK caching client) to limit API calls and cost.
Q6. How do you use S3 for file storage in Java applications?
Short answer:
- The SDK: AWS SDK for Java v2 (
S3Client, or S3AsyncClient, plus the S3 Transfer Manager for multipart and parallel transfers of large files), or Spring Cloud AWS S3Template (s3Template.upload(bucket, key, inputStream)).
- Upload patterns:
- pre-signed URLs (
S3Presigner): the client uploads or downloads directly to or from S3, bypassing your servers (scalable and cheaper), with a short expiry and content-type or size constraints;
- server-side streaming for small files, with no full buffering in memory;
- multipart upload for large files.
- Design:
- key naming (
tenant/orders/2026/09/{uuid}.pdf, no personal data in keys);
- metadata in your database (owner, checksum, content type);
- S3 events (SQS or EventBridge) to trigger processing (virus scan, thumbnails).
- Security:
- Block Public Access;
- bucket policies with least privilege;
- SSE-KMS encryption;
- versioning and Object Lock for audit data;
- CloudFront with signed URLs or origin access control for public content.
- Cost: lifecycle rules (move to IA or Glacier, expire temporary files), and Intelligent-Tiering.
Q7. How do you track logs and metrics with CloudWatch?
Short answer:
- Logs:
- containers log JSON to stdout → the awslogs driver (ECS) or Fluent Bit or FireLens (ECS/EKS) → CloudWatch Logs log groups (with a retention policy);
- query them with Logs Insights (
fields @timestamp, traceId | filter level="ERROR");
- metric filters turn log patterns into metrics.
- Metrics:
- Micrometer's CloudWatch registry (
micrometer-registry-cloudwatch2), or OpenTelemetry → the ADOT collector → CloudWatch (or Amazon Managed Prometheus);
- Container Insights gives ECS/EKS CPU, memory and network;
- ALB metrics (5xx, latency, target health).
- Traces: AWS X-Ray, or OTel with X-Ray or CloudWatch Application Signals.
- Alarms: CloudWatch Alarms on SLO metrics (p99 latency, error rate) → SNS → PagerDuty or Slack. Dashboards per service. Composite alarms to reduce noise.
- Watch out for cost and cardinality: custom metrics are billed per metric and dimension, and log ingestion is billed per GB. Sample verbose logs.
Q8. How do you deploy zero-downtime Spring Boot updates on AWS?
Short answer:
- ECS:
- rolling updates, with
minimumHealthyPercent=100 and maximumPercent=200, plus ALB target-group health checks, a proper deregistration delay, and graceful shutdown (stopTimeout longer than the drain time);
- or blue/green through CodeDeploy (a test listener, traffic shifting canary or linear, automatic rollback on alarms);
- the ECS deployment circuit breaker rolls back automatically on failure.
- EKS: Kubernetes rolling updates with readiness probes, PodDisruptionBudgets and preStop hooks, or Argo Rollouts canaries with the AWS Load Balancer Controller's weighted target groups.
- EC2/ASG: instance refresh, or blue/green ASGs behind the ALB (switching the target groups).
- Application requirements:
server.shutdown=graceful;
- readiness goes down before the stop;
- stateless sessions;
- backward-compatible database migrations (expand/contract);
- consumers that tolerate the old and new message formats.
Q9. What is Elastic Beanstalk, and how does it compare with ECS?
Short answer:
-
Elastic Beanstalk: a PaaS. Upload a JAR, WAR or Docker image, and Beanstalk provisions and manages EC2, the ASG, the ELB, health monitoring, deployment policies (all at once, rolling, immutable, blue/green through a CNAME swap), and logs. It's fast to get started, with little infrastructure knowledge needed. It's less flexible for complex architectures, feels somewhat legacy, and is harder to integrate into modern IaC and GitOps workflows (though CloudFormation-based).
-
ECS: container orchestration, with more control:
- task definitions and services;
- Fargate or EC2 capacity;
- service discovery (Cloud Map, Service Connect);
- fine-grained IAM task roles;
- many services per cluster;
- blue/green through CodeDeploy.
It fits microservices and IaC-driven platforms better.
Choose Beanstalk for simple, single applications and small teams. Choose ECS (or EKS) for multi-service, container-based platforms.
Q10. What are the pros and cons of deploying with Docker on ECS?
Short answer:
- Pros:
- immutable, portable images;
- AWS-native integration: IAM task roles, ALB target groups, CloudWatch, Secrets Manager injection, Cloud Map, App Mesh or Service Connect;
- Fargate removes node management;
- simpler than Kubernetes (less to learn and run);
- rolling or blue-green deployments with a circuit breaker;
- autoscaling built in;
- a good cost-to-effort ratio for AWS-only shops.
- Cons:
- AWS lock-in (task definitions aren't portable);
- a smaller ecosystem than Kubernetes (no Helm or operators, fewer tools);
- less flexible scheduling and networking features;
- Fargate's cost per unit and limits (no GPUs; ephemeral storage limits; startup latency, since image pulls affect scale-out speed);
- some features lag behind Kubernetes (advanced traffic management needs extra services).
Q11. How do you implement load balancing with ALB or ELB on AWS?
Short answer:
- ALB (Application Load Balancer, L7): HTTP/HTTPS/gRPC and WebSockets. Listener rules route by host, path, header or query, to target groups (EC2 instances, IPs for ECS/EKS pods, or Lambda). It supports health checks per target group (
/actuator/health/readiness), TLS termination with ACM certificates, WAF integration, OIDC or Cognito authentication, weighted target groups (canary or blue-green), sticky sessions (avoid them if you can), and slow start.
- NLB (Network Load Balancer, L4): TCP, UDP and TLS, with ultra-low latency, static IPs, and PrivateLink. For non-HTTP protocols, or extreme throughput.
- Classic ELB: legacy, so avoid it.
- With containers: the ECS service registers tasks automatically. On EKS, the AWS Load Balancer Controller creates ALBs from Ingress or Gateway resources (the target type IP, so traffic goes directly to the pods).
- Tune: idle timeout (longer than the application's keep-alive), deregistration delay (longer than the in-flight request time), and cross-zone load balancing.
Q12. What is CloudFront?
Short answer: AWS's CDN. A global network of edge locations caches content close to users:
- static assets and media, from S3 (with Origin Access Control, so the bucket stays private);
- cacheable API responses, from ALB or custom origins, with cache behaviours per path, TTLs and cache keys (headers, cookies, query strings);
- TLS at the edge (ACM certificates), HTTP/2 and HTTP/3;
- AWS WAF and Shield integration (DDoS protection);
- signed URLs or cookies for private content;
- origin failover;
- edge compute (CloudFront Functions, Lambda@Edge) for redirects, headers, A/B testing and authentication checks;
- lower origin load, and better global latency.
Invalidations (/*, which is costly and slow) versus versioned asset filenames (the preferred cache busting).
Follow-up questions this topic invites — and their answers
Q: What is Lambda SnapStart for Java?
A: It snapshots the initialised execution environment (after the init phase), and restores it on cold start, cutting Java cold starts from seconds to hundreds of milliseconds. Be careful with uniqueness (random seeds, connections) captured in the snapshot; use runtime hooks to re-initialise them.
Q: How do ECS tasks get AWS permissions without keys?
A: Through the task role. The ECS agent provides temporary credentials through a credentials endpoint that the SDK's default credential chain discovers. It's separate from the task execution role, which lets ECS pull images and read secrets for the task.
Q: Spot instances for Spring Boot services: yes or no?
A: Yes, for stateless, horizontally scaled services and batch jobs, with diversification across instance types, graceful handling of two-minute interruption notices (drain and deregister), and a baseline of on-demand capacity for availability.
Q: How do you cut data transfer costs?
A: Keep traffic within the same availability zone where possible (zone-aware routing), use VPC endpoints for S3 and DynamoDB (avoiding NAT gateway charges), compress payloads, and cache at the edge with CloudFront.