So using the S3 from the queue off-loads all the big JSON blobs, like the task definition to S3. So the queue never have to store it. Right now I upload the task definition through the queue, because I want the queue to validate task definitions before they are accepted.
We could move to a model where the queue just signs a URL for uploading a task definition.

In any event, I see persistence to S3 as something that happens while tasks are executed. Basically as soon as it's possible, some things like task definition should never be stored in the queue, it should only hold task status structures.

The rationale for having S3 uploads being controlled by the queue is, as detailed above, that the queue will eventually have to deal with authentication and authorization. After all, when a task is submitted it is either accepted or rejected. I see no reason to make another central component to handle authorization and authentication.