📦
Storage service
  • Introduction
  • How-to: basic operations
    • Ingest a bag into the storage service
    • Look up an already-stored bag in the storage service
    • Look up the versions of a bag in the storage service
  • How to: advanced usage
    • Getting notifications of newly stored bags
  • How to: debugging errors
    • Where to find application logs
    • Manually marking ingests as failed
  • Reference/design decisison
    • The semantics of bags, ingests and ingest types
    • How identifiers work in the storage service
    • How files are laid out in the underlying storage
    • Compressed vs uncompressed bags, and the choice of tar.gz
  • Developer information/workflow
    • An API reference for the user-facing storage service APIs
    • Key technologies
    • Inter-app messaging with SQS and SNS
    • How requests are routed from the API to app containers
    • Repository layout
    • How Docker images are published to ECR
  • Wellcome-specific information
    • Our storage configuration
      • Our three replicas: S3, Glacier, and Azure
      • Using multiple storage tiers for cost-efficiency (A/V, TIFFs)
      • Small fluctuations in our storage bill
      • Delete protection on the production storage service
    • Wellcome-specific debugging
      • Why did my callback to Goobi return a 401 Unauthorized?
    • Recovering files from our Azure replica
    • Awkward files and bags
    • Deleting files or bags bags from the storage service
Powered by GitBook
On this page
  • SQS queues and SNS topics
  • Autoscaling based on queue size
  1. Developer information/workflow

Inter-app messaging with SQS and SNS

PreviousKey technologiesNextHow requests are routed from the API to app containers

Last updated 2 years ago

Most of our services form a pipeline: an app receives a message, does some work, then sends another message to the next app in line. This continues until the work is finished (in this case, a bag has been successfully stored).

This is the . This document explains a bit more about our specific implementation.

SQS queues and SNS topics

To receive a message, an app polls an SQS queue. (SQS = Simple Queuing Service)

To send a message, an app sends a notification to an SNS topic. (SNS = Simple Notification Service)

SQS queues can subscribe to an SNS topic, which means every notification sent to the topic is forwarded to the queue -- and in turn, can be received by an app.

At this point, you may ask: why don't apps send directly to queues? Because we don't always have a one-to-one relationship between topics and queues.

Sometimes, we want a notification from one app to be distributed to multiple apps. Multiple queues can subscribe to the same topic:

For example, after the bag versioner has assigned a version to a bag, the notification is forwarded to every replicator at once. This allows replications to occur in parallel, rather than in serial.

This also allows a single app to process notifications from multiple apps. A single queue can subscribe to multiple topics:

For example, all the replicators send messages to the same replica aggregator. The aggregator counts the messages in to see if all the replicators have completed.

Autoscaling based on queue size

Most of the time, the queues are empty and there's nothing for the apps to do. To save money, we can use autoscaling: by default, we aren't running any of our pipeline workers, and we only turn them on when there are messages that need processing.

Specifically, we set up CloudWatch Alarms that monitor the size of each queue:

  • If a queue has messages waiting to be handled, start an instance of the app that reads from that queue (up to a given maximum)

  • If a queue has no messages waiting and no messages in-flight, turn off any running instances of the app

This makes the storage service more cost-efficient, but it means bags can take longer to process than if it was always-on. In our experience, this is a worthwhile tradeoff.

We don't autoscale apps that need to be continuously available -- i.e., the external APIs.

pub/sub (publish-subscribe) pattern