PrepZone Logo
PrepZone

S3, SQS, Secrets on AWS

Integrating AWS services into Boot apps for cloud-native deployments.

Why this matters

  • Storing book cover images on the application server's disk does not scale across pods — S3 gives durable, CDN-fronted object storage with per-request access control.
  • SQS decouples order placement from downstream fulfilment: the API responds fast while a worker processes the queue at its own pace.
  • Secrets Manager rotates database passwords automatically; Spring Cloud AWS injects them at runtime so credentials never appear in application.yml or Docker images.

StreamHub production architecture (AWS)

HTTPSstaticmissAPICLIENT
Mobile / WebStreamHub cli…
NETWORK
Route 53GeoDNS routing
NETWORK
CloudFrontCDN + WAF edge
NETWORK
AWS ALBTLS terminati…
NETWORK
API GatewayJWT · rate li…
STORAGE
Amazon S3media origin
COMPUTE
Amazon EKSAPI · auth · …
DATABASE
ElastiCachesessions · ho…
DATABASE
RDS Postgresprimary + rep…
INTEGRATION
Amazon MSKdomain events
ANALYTICS
OpenSearchstream discov…
OPS
CloudWatchmetrics · X-R…
End-to-end path from user to data — reference this when placing any new service.

AWS services mapped to BookStore needs

  • S3 — book cover images, publisher catalog CSV uploads, generated sales report PDFs.
  • SQS — order fulfilment queue, inventory sync messages, dead-letter queue for failed processing.
  • Secrets Manager — database URLs, API keys, JWT signing secrets.
  • Parameter Store — non-secret configuration like feature flags and service endpoints.
  • Spring Cloud AWS — auto-configuration for S3, SQS, and Secrets Manager in Boot 3.x.

Dependencies

Java
<dependency>
    <groupId>io.awspring.cloud</groupId>
    <artifactId>spring-cloud-aws-starter-s3</artifactId>
</dependency>
<dependency>
    <groupId>io.awspring.cloud</groupId>
    <artifactId>spring-cloud-aws-starter-sqs</artifactId>
</dependency>
<dependency>
    <groupId>io.awspring.cloud</groupId>
    <artifactId>spring-cloud-aws-starter-secrets-manager</artifactId>
</dependency>
Java
spring:
  cloud:
    aws:
      region:
        static: eu-west-1
      credentials:
        profile:
          name: bookstore-prod  # use IAM roles on ECS/EKS, not profiles
  config:
    import:
      - aws-secretsmanager:bookstore/prod/database
      - aws-parameterstore:/bookstore/prod/

S3 for book cover images

Java
@Service
public class CoverImageService {

    private final S3Template s3Template;

    @Value("${bookstore.s3.covers-bucket}")
    private String bucket;

    public String uploadCover(String isbn, MultipartFile file) throws IOException {
        String key = "covers/" + isbn + ".jpg";
        s3Template.upload(bucket, key, file.getInputStream());
        return s3Template.createSignedGetURL(bucket, key, Duration.ofHours(1)).toString();
    }

    public void deleteCover(String isbn) {
        s3Template.deleteObject(bucket, "covers/" + isbn + ".jpg");
    }
}
Java
@RestController
@RequestMapping("/api/books/{isbn}/cover")
public class CoverImageController {

    private final CoverImageService coverImageService;

    @PostMapping
    public ResponseEntity<CoverUploadResponse> upload(
            @PathVariable String isbn,
            @RequestParam("file") MultipartFile file) throws IOException {
        String url = coverImageService.uploadCover(isbn, file);
        return ResponseEntity.ok(new CoverUploadResponse(url));
    }
}

SQS for order fulfilment

Java
@Service
public class OrderFulfilmentPublisher {

    private final SqsTemplate sqsTemplate;

    @Value("${bookstore.sqs.fulfilment-queue}")
    private String queueName;

    public void enqueue(OrderPlacedEvent event) {
        sqsTemplate.send(queueName, OrderFulfilmentMessage.from(event));
    }
}
Java
@Component
public class OrderFulfilmentListener {

    private final FulfilmentService fulfilmentService;

    @SqsListener("${bookstore.sqs.fulfilment-queue}")
    public void processFulfilment(OrderFulfilmentMessage message) {
        fulfilmentService.fulfil(message.orderId(), message.lines());
    }
}
Java
bookstore:
  sqs:
    fulfilment-queue: bookstore-order-fulfilment
    dlq: bookstore-order-fulfilment-dlq

Secrets Manager for database credentials

Java
# Secret stored in AWS Secrets Manager at path: bookstore/prod/database
# { "url": "jdbc:postgresql://...", "username": "bookstore", "password": "..." }

spring:
  datasource:
    url: ${url}
    username: ${username}
    password: ${password}

On ECS or EKS, attach an IAM role with secretsmanager:GetSecretValue and s3:* / sqs:* permissions scoped to BookStore resources — no static credentials in the container.

Quick recall

Everything you need if you only revisit this box.

  • Spring Cloud AWS (io.awspring.cloud) auto-configures S3, SQS, and Secrets Manager clients.
  • Store book covers and reports in S3; generate pre-signed URLs for temporary client access.
  • Use SQS for asynchronous fulfilment work; @SqsListener processes messages with automatic deletion on success.
  • Load secrets via spring.config.import: aws-secretsmanager:... — credentials never touch the image or Git.
  • Use IAM roles in production; reserve local AWS profiles for development only.

Test yourself

Answer these before moving on — recall is what makes it stick.