Since serverless architectures rely on different infrastructure services for different aspects of the app, to implement files handling we'll need to rely on more parts of AWS. This is in contrast to the server-based architecture where most of the functionality was implemented in the backend code.
The most important additions are two S3 buckets: one for the deliverable files and one for the promo images. While it's possible to use just one bucket, it's a best practice to separate protected (deliverable files) content from public (promo image) ones.
The backend itself is implemented as a Lambda function. This is AWS's function-as-a-service offering and while it has a rather strict execution model but if an app can live within those restrictions then it provides an operational environment that scales up and down seamlessly.
Finally, the database now takes the form of DynamoDB tables. This is the truly serverless solution in AWS as it uses a connection-less model necessary to be compatible with Lambda and it can scale up when needed and also back to zero.
Let's discuss these building blocks in a bit more detail!
S3 buckets are containers of objects that can be of virtually any size. S3 is a foundational service in AWS: if you need to store data in a way that is similar to a filesystem, S3 is almost always the right choice. This is because of its durability guarantees, pricing, access control options, and consistency model. Combined all these, storing files in S3 in a serverless app is usually a painless experience.
The durability for each object is 99.999999999% per year. That means you don't need to think about backups in most workloads.
While the pricing page seems daunting at first, but for the simple case it boils down to three parts: data storage, data transfer, and requests. While it takes some time to get familiar with all the nuts and bolts, usually S3 is the cheapest place to store data for a serverless app.