2

On my site I have the ability for users to upload avatars (which they upload to s3). They can only have one avatar at the moment, so I currently just have the filename set to their user id.

However, they may replace their avatars, which causes issues. Because the s3 is propagating to CloudFront, I need to invalidate the cache for the filename when they upload their new avatar (because it replaces the old avatar file). But with CloudFront invalidations are expensive.

It almost seems like Amazon would prefer I just not delete the old files, and instead just give the new avatar a new name and leave the old one in there, even though it's no longer being used by anyone. That way I can avoid the invalidation.

The other option is not to use CloudFront at all, and just upload to s3, and make the s3 bucket public. But the problem with this is that CloudFront is much more generous with their GET request costs and amounts (2,000,000 per month with CloudFront and only 20,000 per month with S3 buckets).

Basically, I have these 3 options, and I'm not sure which to pick, given the above:

1) Replace the files in s3 and then invalidate the file in CloudFront

  • Problem: invalidations are expensive

2) Just dump more files in the s3 bucket and use CloudFront

  • Problem: the old, unused avatars just sit there wasting s3 bucket space

3) Don't use CloudFront, and just replace the file in s3 and then serve it from the bucket

  • Problem: CloudFront has cheaper GET requests and better user experience with latency

Edit: In this case, I'm asking about AWS with s3 and CloudFront. I'm looking to most effectively automate the process by which a user can upload an avatar to my backend service. Specifically, the overwriting of old avatars has me confused. The general process flow of "PreSigned URL -> Upload to s3 -> Propagate via CloudFront" seems an adequate one, but I'm not sure how to accommodate the overwriting of old, no longer used files in this plan, considering the choice seems to be between an expensive invalidation, or the keeping of stale files.

  • Hi there! This question sounds like a vanilla programming problem - can you help us understand how it pertains to DevOps? Are there particular communication, process or automation aspects which you are asking about? Thanks! – Bruce Becker Nov 17 '19 at 7:54
  • 1
    I checked with a couple people and they all recommended I post here, since it's the combination of development and operations. Also, there are a lot of other questions about S3 and CloudFront here. Should I post on StackOverflow instead? Or somewhere else? – Chron Bag Nov 17 '19 at 8:10
  • @ChronBag StackOverflow is restricted to programming questions. I agree with you that you post it on DevOps SE. However, please make it more specific as suggested by BruceBecker by addressing his question: Are there particular communication, process or automation aspects which you are asking about? by adding a new paragraph to the Q&A. – 030 Nov 17 '19 at 10:58
  • Okay, I'm not really sure what that means but I'll try my best. – Chron Bag Nov 17 '19 at 18:47
3

For the best performance naming many small files in an s3 bucket may not be the best idea unless they user_id is a random string. See how the S3 hashing algorithm works https://aws.amazon.com/blogs/aws/amazon-s3-performance-tips-tricks-seattle-hiring-event/

So replacing it by a random hashed value may not be that bad. Of course you need to store the hash in the user profile or you need to calculate it from something. If you add something like profile id or last changed timestamp you can do sha1/md5 of (userid+lastchanged) and if you update timestamp you has the hash of the current avatar.

The older one you can simply delete. CloudFront will remove it from its cache after expiration https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Expiration.html

This will more complex algorithm, but if the costs are the concern, a little bit of extra work seems to be a reasonable approach. Not sure how do you handle the uploads, but it may be a good opportunity to play a bit with step functions which would make sure that the new avatar is uploaded correctly and then the old one is removed as well.

It's kind of a programming question, but I get your point - it is very specific to AWS environment and requires a particular knowledge about how the infrastructure works.

| improve this answer | |
  • Okay, I think you're saying to go with Option 2 because it's not as bad as I thought because if an object goes long enough without being accessed it will be removed from the CloudFront edge nodes? And that storage space in s3 is basically infinite anyway so it's fine to have data in there even if it isn't accessed? – Chron Bag Nov 18 '19 at 6:46
  • yes, option 2. I think I tried to suggest that it should not be that complicated to delete the old avatar at the point where you are uploading the new version, so you do not even waste the space. But it is an optional step. – Petr Chloupek Nov 18 '19 at 14:57
  • I'm not sure how I would delete the old avatar without it being possible for other malicious users to delete other user's avatars. Considering I send the user the presigned URL for uploading to S3, and then they send back their new avatar name, which I set on the server. (I have to trust that they send back the proper filename). I can't set their avatar in the database when they just request the presigned URL, because the upload might fail, or they might cancel it. So my only option is to set it later, no? – Chron Bag Nov 18 '19 at 20:01
  • This starts to seem like a very unusual design pattern. "I have to trust" for sure sounds like a big design flaw. With the presign url you decide how the object will be named before passing the presign url to the user. You can also send user metadata with that URL (e.g. user-id) stackoverflow.com/questions/37614286/… then once the object is successfully uploaded it can trigger a lambda. lambda will read the user-id and can update the db, if there is already another avatar in the db it can delete it without any issues. – Petr Chloupek Nov 18 '19 at 21:05
  • Well, I'm not sure of a way around the trust. You have to update the database column 'avatar' with the name of the object in s3. It would be ideal if I could update the column when generating the presigned URL, but that would be flawed, because the user may just not use the presigned URL. For example, if you update the column and then the user fails their upload to s3, it's too late, because the column is already updated in the database. And you can't just save the presigned URL in the database, because if the user used a different presigned URL, then the filename wouldn't match. – Chron Bag Nov 18 '19 at 22:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.