<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.2.0">Jekyll</generator><link href="https://brianklaas.net/feed.xml" rel="self" type="application/atom+xml" /><link href="https://brianklaas.net/" rel="alternate" type="text/html" /><updated>2022-10-12T08:41:35-04:00</updated><id>https://brianklaas.net/feed.xml</id><title type="html">Brian Klaas</title><subtitle>AWS. Educational Technology. CFML. Presentation Design.</subtitle><entry><title type="html">Slides from My ColdFusion Summit Presentation on Creating Complex Serverless Workflows with CFML at the Center</title><link href="https://brianklaas.net/aws/coldfusion/conferences/2022/10/12/slides-from-cfsummit2022-presentation.html" rel="alternate" type="text/html" title="Slides from My ColdFusion Summit Presentation on Creating Complex Serverless Workflows with CFML at the Center" /><published>2022-10-12T08:39:00-04:00</published><updated>2022-10-12T08:39:00-04:00</updated><id>https://brianklaas.net/aws/coldfusion/conferences/2022/10/12/slides-from-cfsummit2022-presentation</id><content type="html" xml:base="https://brianklaas.net/aws/coldfusion/conferences/2022/10/12/slides-from-cfsummit2022-presentation.html">&lt;p&gt;This year marked the tenth anniversary of the &lt;a href=&quot;https://cfsummit.adobeevents.com&quot;&gt;Adobe ColdFusion Summit&lt;/a&gt;. It was great to get back together with so many familiar faces (and friends!) in person. I’ve attended all of the ColdFusion Summits and, I think, have spoken at all of them as well. I spoke at Summit this year about my favorite topic: ColdFusion and Amazon Web Services.&lt;/p&gt;

&lt;p&gt;“Serverless Beyond Simple: Creating Complex Workflows with ColdFusion at the Center” is an architectural overview of what it takes to build resilient, complex serverless workflows in AWS that are controlled and managed by ColdFusion. The presentation is a distillation of many years of experience in building ColdFusion-based serverless workflows. Even if you’re just getting started with serverless technologies, there’s useful guidance in there for you. The presentation covers Simple Queue Service (SQS) vs. Simple Notification Service (SNS), the power of orchestration in AWS Step Functions, and managing the state of workflows in both locally and in DynamoDB. I’d be remiss if I didn’t also say (as I did in the presentation) that the architectural patterns also apply to building workflows in Google Cloud and Azure.&lt;/p&gt;

&lt;p&gt;A &lt;a href=&quot;https://brianklaas.net/assets/pdf/CFSummit2022-ServerlessNotSimple.pdf&quot;&gt;PDF of the slides&lt;/a&gt; from the presentation is available. None of this year’s ColdFusion Summit sessions were recorded, so there is no video for me to share with you.&lt;/p&gt;

&lt;p&gt;If you have any questions about this content in this presentation, feel free to &lt;a href=&quot;https://twitter.com/brian_klaas&quot;&gt;reach out to me on the Twitter&lt;/a&gt;!&lt;/p&gt;</content><author><name></name></author><category term="AWS" /><category term="ColdFusion" /><category term="Conferences" /><summary type="html">This year marked the tenth anniversary of the Adobe ColdFusion Summit. It was great to get back together with so many familiar faces (and friends!) in person. I’ve attended all of the ColdFusion Summits and, I think, have spoken at all of them as well. I spoke at Summit this year about my favorite topic: ColdFusion and Amazon Web Services.</summary></entry><entry><title type="html">Slides and Recording from My ColdFusion Developer Week Presentation on Advanced Features of S3</title><link href="https://brianklaas.net/aws/coldfusion/conferences/2022/08/16/Resources-from-S3-CF2021-presentation.html" rel="alternate" type="text/html" title="Slides and Recording from My ColdFusion Developer Week Presentation on Advanced Features of S3" /><published>2022-08-16T12:18:00-04:00</published><updated>2022-08-16T12:18:00-04:00</updated><id>https://brianklaas.net/aws/coldfusion/conferences/2022/08/16/Resources-from-S3-CF2021-presentation</id><content type="html" xml:base="https://brianklaas.net/aws/coldfusion/conferences/2022/08/16/Resources-from-S3-CF2021-presentation.html">&lt;p&gt;I’m grateful that I’ve spoken at Adobe’s ColdFusion Developer Week over the years. This is a great opportunity for those interested in Adobe ColdFusion or the CFML language to get a wide variety of &lt;em&gt;free&lt;/em&gt; training about ColdFusion and CFML. I spoke at CF Dev Week again this year about my favorite topic: ColdFusion and Amazon Web Services.&lt;/p&gt;

&lt;p&gt;Although I spoke about &lt;a href=&quot;https://aws.amazon.com/s3/&quot;&gt;Simple Storage Service (S3)&lt;/a&gt; at CF Dev Week in years past, this presentation looked at how to take advantage of more advanced features of S3 using the native features of Adobe ColdFusion 2021. All of the code samples in the presentation work in Adobe ColdFusion 2021. If you happen to run ColdFusion 2018, 2016, or even ColdFusion 11, my &lt;a href=&quot;https://github.com/brianklaas/awsPlaybox&quot;&gt;AWS Playbox repo&lt;/a&gt; has code which shows you how to do the very same things using the very powerful AWS Java SDK.&lt;/p&gt;

&lt;p&gt;Below are the links to the two resources from the presentation: the slides and the recording of the presentation on YouTube:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A &lt;a href=&quot;https://brianklaas.net/assets/pdf/CFDevWeek2022-S3.pdf&quot;&gt;PDF of the slides&lt;/a&gt; from the presentation&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=-B8nLgtqQ-8&amp;amp;list=PL3iywAijqFoW7Gc4rYpfdx5jg7v2tiAyF&amp;amp;index=16&amp;amp;ab_channel=adobecoldfusion&quot;&gt;Presentation recording&lt;/a&gt; on YouTube&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you have any questions about this content in this presentation, feel free to &lt;a href=&quot;https://twitter.com/brian_klaas&quot;&gt;reach out to me on the Twitter&lt;/a&gt;!&lt;/p&gt;</content><author><name></name></author><category term="AWS" /><category term="ColdFusion" /><category term="Conferences" /><summary type="html">I’m grateful that I’ve spoken at Adobe’s ColdFusion Developer Week over the years. This is a great opportunity for those interested in Adobe ColdFusion or the CFML language to get a wide variety of free training about ColdFusion and CFML. I spoke at CF Dev Week again this year about my favorite topic: ColdFusion and Amazon Web Services.</summary></entry><entry><title type="html">Resources from Scalable, Responsive Apps and Services with Queues and Pub/Sub Mechanisms</title><link href="https://brianklaas.net/aws/coldfusion/conferences/2021/12/27/Resources-from-scaling-apps-with-SQS-and-SNS-presentation.html" rel="alternate" type="text/html" title="Resources from Scalable, Responsive Apps and Services with Queues and Pub/Sub Mechanisms" /><published>2021-12-27T08:18:00-05:00</published><updated>2021-12-27T08:18:00-05:00</updated><id>https://brianklaas.net/aws/coldfusion/conferences/2021/12/27/Resources-from-scaling-apps-with-SQS-and-SNS-presentation</id><content type="html" xml:base="https://brianklaas.net/aws/coldfusion/conferences/2021/12/27/Resources-from-scaling-apps-with-SQS-and-SNS-presentation.html">&lt;p&gt;In spite of the pandemic, the &lt;a href=&quot;https://coldfusion.adobe.com&quot;&gt;Adobe ColdFusion&lt;/a&gt; team held not one but two virtual conferences this calendar year about all things ColdFusion. In addition to helping organize the speakers, I also spoke at both versions of the conference. As usual, I spoke about leveraging the power of cloud-based services to improve on the scalability, reliability, and performance of your ColdFusion applications. This year’s topic was “Scalable, Responsive Apps and Services with Queues and Pub/Sub Mechanisms,” which focused on Amazon Web Services’ &lt;a href=&quot;https://aws.amazon.com/sqs/&quot;&gt;Simple Queue Service&lt;/a&gt; and &lt;a href=&quot;https://aws.amazon.com/sns/&quot;&gt;Simple Notification Service&lt;/a&gt;, both of which are easy to use from within ColdFusion.&lt;/p&gt;

&lt;p&gt;Below are the resources from the presentation: a PDF copy of the slides, and a link to my AWS Playbox repo on GitHub. The AWS Playbox repo has examples of using both SQS and SNS via the &lt;a href=&quot;https://sdk-for-java.amazonwebservices.com/latest/aws-java-sdk.zip&quot;&gt;AWS Java SDK&lt;/a&gt;. This is the route you have to go if you’re using any version of ColdFusion prior to ColdFusion 2021.&lt;/p&gt;

&lt;p&gt;The ColdFusion team will post videos from all sessions at the conference on &lt;a href=&quot;https://coldfusion.adobe.com/videos/&quot;&gt;the ColdFusion Community portal&lt;/a&gt;. Until they do that, though, you can view the recordings on &lt;a href=&quot;https://cfsummit.vconfex.com/&quot;&gt;the conference site&lt;/a&gt;. The always-helpful Charlie Arehart has a post on the community portal that walks you through &lt;a href=&quot;https://coldfusion.adobe.com/2021/12/viewing-coldfusion-summit-2021-recordings/&quot;&gt;finding the recordings&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A &lt;a href=&quot;https://brianklaas.net/assets/pdf/CFSummitDec2021-SQSandSNS.pdf&quot;&gt;PDF of the slides&lt;/a&gt; from the presentation&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/brianklaas/awsPlaybox&quot;&gt;AWS Playbox Repo&lt;/a&gt; on GitHub&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you have any questions about this content in this presentation, feel free to &lt;a href=&quot;https://twitter.com/brian_klaas&quot;&gt;reach out to me on the Twitter&lt;/a&gt;!&lt;/p&gt;</content><author><name></name></author><category term="AWS" /><category term="ColdFusion" /><category term="Conferences" /><summary type="html">In spite of the pandemic, the Adobe ColdFusion team held not one but two virtual conferences this calendar year about all things ColdFusion. In addition to helping organize the speakers, I also spoke at both versions of the conference. As usual, I spoke about leveraging the power of cloud-based services to improve on the scalability, reliability, and performance of your ColdFusion applications. This year’s topic was “Scalable, Responsive Apps and Services with Queues and Pub/Sub Mechanisms,” which focused on Amazon Web Services’ Simple Queue Service and Simple Notification Service, both of which are easy to use from within ColdFusion.</summary></entry><entry><title type="html">Resources from My ColdFusion Summit 2020 Presentation on cflambda</title><link href="https://brianklaas.net/aws/coldfusion/conferences/2020/11/17/Resources-from-cflambda-presentation.html" rel="alternate" type="text/html" title="Resources from My ColdFusion Summit 2020 Presentation on cflambda" /><published>2020-11-17T08:18:00-05:00</published><updated>2020-11-17T08:18:00-05:00</updated><id>https://brianklaas.net/aws/coldfusion/conferences/2020/11/17/Resources-from-cflambda-presentation</id><content type="html" xml:base="https://brianklaas.net/aws/coldfusion/conferences/2020/11/17/Resources-from-cflambda-presentation.html">&lt;p&gt;This week, I’m speaking at the &lt;a href=&quot;https://cfsummit.adobeevents.com/schedule/&quot;&gt;ColdFusion Summit 2020&lt;/a&gt; about “Building Serverless ColdFusion Applications with cflambda.” &lt;a href=&quot;https://helpx.adobe.com/coldfusion/using/aws-serverless-coldfusion.ug.html&quot;&gt;cflambda&lt;/a&gt; is a new release from the Adobe ColdFusion team that’s part of &lt;a href=&quot;https://community.adobe.com/t5/coldfusion/introducing-adobe-coldfusion-2021-release/m-p/11585468?page=1#M186888&quot;&gt;ColdFusion 2021&lt;/a&gt; and which lets you write AWS Lambda functions in ColdFusion. There are a number of resources referenced in the presentation that I’d like to share in this post:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A &lt;a href=&quot;https://brianklaas.net/assets/pdf/CFSummit2020-cflambda.pdf&quot;&gt;PDF of the slides&lt;/a&gt; from the presentation&lt;/li&gt;
  &lt;li&gt;The &lt;a href=&quot;https://brianklaas.net/assets/code/exampleCodeFromCflambdaPreso.zip&quot;&gt;cflambda function code&lt;/a&gt; from the presentation&lt;/li&gt;
  &lt;li&gt;Paul Kukiel’s &lt;a href=&quot;https://github.com/kukielp/acf-lambda&quot;&gt;sample API Gateway Lambda repo&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://aws.amazon.com/serverless/sam/&quot;&gt;AWS SAM (Serverless Application Model)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More examples of calling Lambda functions — and other AWS services — from your ColdFusion applications can be found in my &lt;a href=&quot;https://github.com/brianklaas/awsPlaybox&quot;&gt;AWS Playbox repo on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Below are the recordings of two related presentations that I mentioned during this talk:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=ucn90XLDlPw&quot;&gt;IAM: Build Fine-Grained Control of Amazon Web Services in Your ColdFusion App&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=eNcOfG9Vkbg&amp;amp;list=PLG2EHzEbhy0-QirMKgSxhjkUyTSSTvHjL&quot;&gt;I Didn’t Know S3 Could Do That!&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you have any questions about this content in this presentation, feel free to &lt;a href=&quot;https://twitter.com/brian_klaas&quot;&gt;reach out to me on the Twitter&lt;/a&gt;!&lt;/p&gt;</content><author><name></name></author><category term="AWS" /><category term="ColdFusion" /><category term="Conferences" /><summary type="html">This week, I’m speaking at the ColdFusion Summit 2020 about “Building Serverless ColdFusion Applications with cflambda.” cflambda is a new release from the Adobe ColdFusion team that’s part of ColdFusion 2021 and which lets you write AWS Lambda functions in ColdFusion. There are a number of resources referenced in the presentation that I’d like to share in this post:</summary></entry><entry><title type="html">Slides and Recording from my CFMeetup Presentation: I Didn’t Know S3 Could Do That!</title><link href="https://brianklaas.net/aws/coldfusion/conferences/2020/08/10/Slides-Recording-Cfmeetup-S3-Presentation.html" rel="alternate" type="text/html" title="Slides and Recording from my CFMeetup Presentation: I Didn’t Know S3 Could Do That!" /><published>2020-08-10T09:08:00-04:00</published><updated>2020-08-10T09:08:00-04:00</updated><id>https://brianklaas.net/aws/coldfusion/conferences/2020/08/10/Slides-Recording-Cfmeetup-S3-Presentation</id><content type="html" xml:base="https://brianklaas.net/aws/coldfusion/conferences/2020/08/10/Slides-Recording-Cfmeetup-S3-Presentation.html">&lt;p&gt;Thanks to the amazing &lt;a href=&quot;http://www.carehart.org&quot;&gt;Charlie Arehart&lt;/a&gt; for hosting me on last week’s &lt;a href=&quot;https://www.meetup.com/coldfusionmeetup/&quot;&gt;CFMeetup&lt;/a&gt;. My presentation — “I Didn’t Know S3 Could Do That!” — covered a lot of the same material that is in &lt;a href=&quot;http://brianklaas.net/aws/coldfusion/2020/05/06/New-Series-Using-S3-in-CFML.html&quot;&gt;my recent series on using S3 in CFML&lt;/a&gt;. There were a lot of really good questions, and I very much enjoyed my time delivering the presentation.&lt;/p&gt;

&lt;p&gt;You can &lt;a href=&quot;https://brianklaas.net.s3.us-east-1.amazonaws.com/assets/pdf/CFMeetupAug2020-S3.pdf&quot;&gt;download the slides&lt;/a&gt; from the presentation, or &lt;a href=&quot;https://www.youtube.com/watch?v=eNcOfG9Vkbg&amp;amp;list=PLG2EHzEbhy0-QirMKgSxhjkUyTSSTvHjL&quot;&gt;watch the whole presentation&lt;/a&gt; on YouTube.&lt;/p&gt;</content><author><name></name></author><category term="AWS" /><category term="ColdFusion" /><category term="Conferences" /><summary type="html">Thanks to the amazing Charlie Arehart for hosting me on last week’s CFMeetup. My presentation — “I Didn’t Know S3 Could Do That!” — covered a lot of the same material that is in my recent series on using S3 in CFML. There were a lot of really good questions, and I very much enjoyed my time delivering the presentation.</summary></entry><entry><title type="html">Beyond the Basics of Using AWS S3 in CFML: Editing Tags and Using S3 Object Metadata</title><link href="https://brianklaas.net/aws/coldfusion/2020/08/03/Beyond-Basics-S3-Editing-Tags-and-Metadata.html" rel="alternate" type="text/html" title="Beyond the Basics of Using AWS S3 in CFML: Editing Tags and Using S3 Object Metadata" /><published>2020-08-03T09:55:00-04:00</published><updated>2020-08-03T09:55:00-04:00</updated><id>https://brianklaas.net/aws/coldfusion/2020/08/03/Beyond-Basics-S3-Editing-Tags-and-Metadata</id><content type="html" xml:base="https://brianklaas.net/aws/coldfusion/2020/08/03/Beyond-Basics-S3-Editing-Tags-and-Metadata.html">&lt;p&gt;In &lt;a href=&quot;https://brianklaas.net/aws/coldfusion/2020/07/27/Beyond-Basics-S3-Tags.html&quot;&gt;the last post in this series&lt;/a&gt;, we looked at how to add tags to an object uploaded to S3 via the AWS Java SDK. What if you need to change those tags? Are tags the &lt;em&gt;only&lt;/em&gt; way to add metadata to objects in S3? Let’s file out.&lt;/p&gt;

&lt;h2 id=&quot;updating-object-tags-in-s3&quot;&gt;Updating Object Tags in S3&lt;/h2&gt;

&lt;p&gt;It’s possible to update the tags assigned to an object in S3. This is particularly important if you already have files in S3 without tags. To do this, you’ll tell the S3 client in your application to run a setObjectTagging() request:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;tag&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;CreateObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;com.amazonaws.services.s3.model.Tag&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tagKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;tagValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;fileTagging&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;CreateObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;com.amazonaws.services.s3.model.ObjectTagging&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Remember: &quot;key name&quot; is the path to the file (incuding the file name) in the bucket&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;objectTaggingRequest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;CreateObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;com.amazonaws.services.s3.model.SetObjectTaggingRequest&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bucketName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;keyName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fileTagging&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;s3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setObjectTagging&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;objectTaggingRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;It’s important to note that when you run a setObjectTagging() request, it &lt;em&gt;replaces&lt;/em&gt; the existing tags on the object. There’s no way to just “update” the tags on an object.&lt;/p&gt;

&lt;h2 id=&quot;tags-vs-metadata&quot;&gt;Tags vs. Metadata&lt;/h2&gt;

&lt;p&gt;When you put a file in S3, &lt;a href=&quot;https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html&quot;&gt;S3 automatically adds quite a bit of metadata&lt;/a&gt;, including:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Content-Length&lt;/li&gt;
  &lt;li&gt;Content-Type&lt;/li&gt;
  &lt;li&gt;Last-Modified&lt;/li&gt;
  &lt;li&gt;x-amz-server-side-encryption&lt;/li&gt;
  &lt;li&gt;x-amz-storage-class&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and more. If some of these look like regular, plain http response headers, that’s because they are.&lt;/p&gt;

&lt;p&gt;If you want to add your own custom metadata to an object in S3, you can add metadata instead of tags. Tags are not the same thing as object metadata in S3. Metadata applies only to that object in S3 and cannot be searched on, as you can search with tags.&lt;/p&gt;

&lt;p&gt;To set an object’s metadata, you would set the objectMetadata object on your putFileRequest, as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;objectMetadata&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;CreateObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;com.amazonaws.services.s3.model.ObjectMetadata&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;objectMetadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setUserMetadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;plainOldCFStructOfMetaData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;putFileRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setObjectMetadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;objectMetadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You can read the metadata for an object in S3 when you run a getObject() or &lt;a href=&quot;https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/model/GetObjectMetadataRequest.html&quot;&gt;GetObjectMetadataRequest()&lt;/a&gt; request. The metadata is also sent in the response headers of every plain http request to an object in S3 (ie; https://somebucket.s3.amazonaws.com/somePhoto.jpg).&lt;/p&gt;

&lt;p&gt;It’s important to note that you cannot edit or change the metadata for an object once that object is created. If you need to do this, you have copy the object into the same place (effectively overwriting the file) with a &lt;a href=&quot;https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/model/CopyObjectRequest.html&quot;&gt;CopyObjectRequest&lt;/a&gt; object with the new metadata. It’s not convenient, but if you have metadata that you want to come down with every plain http request to an object in S3, metadata is the only way to go. Tags are not included in plain http requests to objects in S3.&lt;/p&gt;

&lt;p&gt;That’s it for object tags and metadata in S3. As always, if you have any questions about this, feel free to &lt;a href=&quot;https://twitter.com/brian_klaas&quot;&gt;message me on the Twitter&lt;/a&gt;.&lt;/p&gt;</content><author><name></name></author><category term="AWS" /><category term="ColdFusion" /><summary type="html">In the last post in this series, we looked at how to add tags to an object uploaded to S3 via the AWS Java SDK. What if you need to change those tags? Are tags the only way to add metadata to objects in S3? Let’s file out.</summary></entry><entry><title type="html">Beyond the Basics of Using AWS S3 in CFML: The Why and How of Adding Tags to Your Files</title><link href="https://brianklaas.net/aws/coldfusion/2020/07/27/Beyond-Basics-S3-Tags.html" rel="alternate" type="text/html" title="Beyond the Basics of Using AWS S3 in CFML: The Why and How of Adding Tags to Your Files" /><published>2020-07-27T08:51:00-04:00</published><updated>2020-07-27T08:51:00-04:00</updated><id>https://brianklaas.net/aws/coldfusion/2020/07/27/Beyond-Basics-S3-Tags</id><content type="html" xml:base="https://brianklaas.net/aws/coldfusion/2020/07/27/Beyond-Basics-S3-Tags.html">&lt;p&gt;As anyone who has worked in any of the major cloud service providers will tell you, there will be ever-increasing sprawl the more you use a cloud provider: more files, more servers, more databases, more accounts, more services, more everything. This is especially the case with object storage like S3. You can easily end up with tens or hundreds of thousands of files in a month. If you were to look at any one of the files in a bucket, could you say who put that file there? Could you look at all the files and be able to charge each file owner for the storage cost? Not without the power of tags.&lt;/p&gt;

&lt;h2 id=&quot;tags-in-aws&quot;&gt;Tags in AWS&lt;/h2&gt;

&lt;p&gt;Tags are metadata-like key-value pairs you can apply to nearly anything in AWS. You determine the key and you determine the value and then apply the tags to a resource in AWS. You can then use those tags when you search for resources (including files in S3) inside AWS. You can even enable a special kind of tag — a &lt;a href=&quot;https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/cost-alloc-tags.html&quot;&gt;cost-allocation tag&lt;/a&gt; — that will be used to break down individual “ownership” costs of each service on your monthly AWS bill. Most people use tags to determine things like the:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Department which owns the resource (“department” : “marketing”)&lt;/li&gt;
  &lt;li&gt;Environment in which the resource runs (“environment” : “dev”)&lt;/li&gt;
  &lt;li&gt;Application to which the resource belongs (“application” : “order fulfillment”)&lt;/li&gt;
  &lt;li&gt;Security level of the resource (“compliance” : “hippa”)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tags can represent anything, so it’s important that you:&lt;/p&gt;

&lt;p&gt;a. start tagging your resources as soon as possible&lt;br /&gt;
b. have a strategy for coming up with tags&lt;/p&gt;

&lt;p&gt;AWS sees how hundreds of thousands of customers tag their resources and have come up with &lt;a href=&quot;https://aws.amazon.com/answers/account-management/aws-tagging-strategies/&quot;&gt;a really useful guide to tagging strategies&lt;/a&gt;. It’s worth a read when you’re coming up with your own plan for tagging.&lt;/p&gt;

&lt;h2 id=&quot;adding-tags-to-files-in-s3&quot;&gt;Adding Tags to Files in S3&lt;/h2&gt;

&lt;p&gt;Adding tags to files in S3 is very much like adding tags to any resource in AWS. You create tags, and then add them to a request to create or modify a resource in AWS. In the case of S3, you create your tags, add them to an ObjectTagging object, and then add that ObjectTagging object to the putObject request that actually uploads your file to S3.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;s3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;awsServiceFactory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createServiceObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;s3&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;javaFileObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;CreateObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;java.io.File&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fileLocation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;putFileRequest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;CreateObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;com.amazonaws.services.s3.model.PutObjectRequest&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bucketName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fileName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;javaFileObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Here&apos;s where we add our tag&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;tag&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;CreateObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;com.amazonaws.services.s3.model.Tag&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tagKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;tagValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;fileTagging&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;CreateObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;com.amazonaws.services.s3.model.ObjectTagging&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;putFileRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setTagging&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fileTagging&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;s3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;putObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;putFileRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The code above should be fairly self-explanatory, but here’s a quick rundown. First, you create a putFileRequest using a standard Java File object. (&lt;a href=&quot;https://brianklaas.net/aws/coldfusion/2020/05/08/Beyond-Basics-S3-Upload-File-via-AWS-Java-SDK.html&quot;&gt;Read more about uploading files to S3 via the AWS Java SDK&lt;/a&gt;.) Next, you create a Tag object, assigning it the key and value with which you want to tag the file. Next, the tag(s) are added to an ObjectTagging object, which is a standard object throughout the AWS Java SDK. Finally, you set the tagging on the putFileRequest object using the ObjectTagging object. When the file is actually uploaded to S3, the tags are added to the file.&lt;/p&gt;

&lt;p&gt;It’s really straightforward to add tags to the objects you put in S3, so start doing it! In the next post in this series, we’ll look at editing object tags, and the differences between tags and object metadata in S3.&lt;/p&gt;</content><author><name></name></author><category term="AWS" /><category term="ColdFusion" /><summary type="html">As anyone who has worked in any of the major cloud service providers will tell you, there will be ever-increasing sprawl the more you use a cloud provider: more files, more servers, more databases, more accounts, more services, more everything. This is especially the case with object storage like S3. You can easily end up with tens or hundreds of thousands of files in a month. If you were to look at any one of the files in a bucket, could you say who put that file there? Could you look at all the files and be able to charge each file owner for the storage cost? Not without the power of tags.</summary></entry><entry><title type="html">Beyond the Basics of Using AWS S3 in CFML: File Versioning in S3 Buckets</title><link href="https://brianklaas.net/aws/coldfusion/2020/07/13/Beyond-Basics-S3-Versioning.html" rel="alternate" type="text/html" title="Beyond the Basics of Using AWS S3 in CFML: File Versioning in S3 Buckets" /><published>2020-07-13T10:01:00-04:00</published><updated>2020-07-13T10:01:00-04:00</updated><id>https://brianklaas.net/aws/coldfusion/2020/07/13/Beyond-Basics-S3-Versioning</id><content type="html" xml:base="https://brianklaas.net/aws/coldfusion/2020/07/13/Beyond-Basics-S3-Versioning.html">&lt;p&gt;When editing files of any kind, users of modern applications expect to have access to previous versions of the file, and undo work that they don’t like or made in error. Implementing a versioning system isn’t easy, especially when file systems are generally set up to only allow one “copy” of any given file. It’s often up to you, the developer, to handle the versioning and ensure that new versions of uploaded files don’t overwrite older ones.&lt;/p&gt;

&lt;p&gt;Fortunately, it’s exactly this kind of undifferentiated heavy lifting at which AWS excels. Why should you worry about file versioning at the file system level, when you can utilize this as a cheap service? &lt;a href=&quot;https://docs.aws.amazon.com/AmazonS3/latest/dev/Versioning.html&quot;&gt;Versioning is built in to S3&lt;/a&gt;, and comes at no additional cost — except for all the copies of the files that you store.&lt;/p&gt;

&lt;h2 id=&quot;enabling-file-versioning-in-cfml&quot;&gt;Enabling File Versioning in CFML&lt;/h2&gt;

&lt;p&gt;Versioning is enabled on per-bucket basis. There’s no way to say “just version this file,” or even provide a path prefix that says “only affect these files in this path,” as you can do with &lt;a href=&quot;https://brianklaas.net/aws/coldfusion/2020/06/16/Beyond-Basics-S3-Lifecycle-Rules.html&quot;&gt;lifecycle rules&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As always, the full code for this and all of my demos can be found in my &lt;a href=&quot;https://github.com/brianklaas/awsPlaybox&quot;&gt;AWSPlaybox GitHub repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here’s how you enable versioning on a bucket in CFML:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;s3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;awsServiceFactory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createServiceObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;s3&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;bucketVersioningConfig&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;CreateObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;com.amazonaws.services.s3.model.BucketVersioningConfiguration&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;withStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Enabled&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;bucketVersioningConfigRequest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;CreateObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;com.amazonaws.services.s3.model.SetBucketVersioningConfigurationRequest&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bucketName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bucketVersioningConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;s3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setBucketVersioningConfiguration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bucketVersioningConfigRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;It’s quite simple: you create a bucket versioning config object, set the status to “enabled” and tell the S3 bucket to utilize that new configuration.&lt;/p&gt;

&lt;p&gt;Once you have versioning enabled, S3 will store a new version every time you POST a new version of the same file (the same file path/”prefix”) in the same bucket. The response object returned from a PutFile() request to S3 &lt;a href=&quot;https://brianklaas.net/aws/coldfusion/2020/05/08/Beyond-Basics-S3-Upload-File-via-AWS-Java-SDK.html&quot;&gt;using the AWS Java SDK&lt;/a&gt; will give you the version ID of that version of the file which you just uploaded. You’ll need to store that ID in your own application along with some kind of metadata about what that version of the file represents. S3 will not tell you the differences in the content between different versions of a file. It’s not Git. That’s not what it is designed to do. It simply shows all the versions of the file in the bucket. It’s up to you to keep track of what each version represents, or a summary of changes between versions.&lt;/p&gt;

&lt;h2 id=&quot;listing-versions-of-a-file-in-cfml&quot;&gt;Listing Versions of a File in CFML&lt;/h2&gt;

&lt;p&gt;It’s pretty straightforward to retrieve the versions of a file:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;listVersionsRequest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;CreateObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;com.amazonaws.services.s3.model.ListVersionsRequest&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;withBucketName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bucketName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;withPrefix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pathToFileForVersioning&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;withMaxResults&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;versionsResult&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;s3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;listVersions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;listVersionsRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;summariesArray&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;versionsResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getVersionSummaries&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;summariesArray&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;objectSummary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;resultData&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Key: &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;objectSummary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;, versionID: &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;objectSummary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getVersionId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The ListVersionsRequest object is what does the work. It has a number of methods for specifying the data you want returned, but the primary required property (beyond the bucket name) is set via the withPrefix() method. It’s here that you specify the path to the file in the bucket. You can think of a path to a file in a versioned bucket like a folder that contains all the versions of a file therein. The ListVersionsRequest simply shows you all the files in that “folder.” Using the withMaxResults() method limits you to the [n] most recent versions of that file.&lt;/p&gt;

&lt;p&gt;Once you tell S3 to list the verisons for that prefix, it returns, within the request result object, an array of summaries about each version of the file. Again, it’s not going to tell you what’s different in the content between each version. You’ve got to track that on your own. You can loop through the summaries array to get the IDs of each version of the file (the “key”) that you will match to data in your own application about what each version represents.&lt;/p&gt;

&lt;h2 id=&quot;warning-cost-increases-ahead&quot;&gt;Warning: Cost Increases Ahead!&lt;/h2&gt;

&lt;p&gt;It’s important to remember that while you get all of the versioning functionality in S3 for free, you pay for every version of every file stored. If a file is deleted out of a bucket that has versioning enabled, the file isn’t actually deleted. A deletion marker is placed on the file so that it can be un-deleted at a later time. If versioning is disabled on a bucket, all the old versions of each file are retained for safety’s sake.&lt;/p&gt;

&lt;p&gt;All of these versions of files start to add up over time. It’s important to delete older versions of files. There is no way to limit the number of versions kept, or to set a maximum number of versions per file and automatically delete files older than that maximum.&lt;/p&gt;

&lt;p&gt;You’re best off building tasks to check for old versions manually, or to &lt;a href=&quot;https://brianklaas.net/aws/coldfusion/2020/06/02/Beyond-Basics-S3-Storage-Classes.html&quot;&gt;use a lifecycle&lt;/a&gt; rule to have old versions automatically expire after a period of time. The BucketLifecycleConfiguration.Rule. setNoncurrentVersionExpirationInDays(int) method will help you do this transparently.&lt;/p&gt;

&lt;p&gt;Versioning is a powerful tool and an easy addition to any S3 bucket. Just watch out for those unintented cost increases. As always, if you have any questions about this, feel free to &lt;a href=&quot;https://twitter.com/brian_klaas&quot;&gt;message me on the Twitter&lt;/a&gt;.&lt;/p&gt;</content><author><name></name></author><category term="AWS" /><category term="ColdFusion" /><summary type="html">When editing files of any kind, users of modern applications expect to have access to previous versions of the file, and undo work that they don’t like or made in error. Implementing a versioning system isn’t easy, especially when file systems are generally set up to only allow one “copy” of any given file. It’s often up to you, the developer, to handle the versioning and ensure that new versions of uploaded files don’t overwrite older ones.</summary></entry><entry><title type="html">Beyond the Basics of Using AWS S3 in CFML: Use Lifecycle Rules to Automatically Delete Files After a Period of Time</title><link href="https://brianklaas.net/aws/coldfusion/2020/06/22/Beyond-Basics-S3-Lifecycle-Rules-Deletion.html" rel="alternate" type="text/html" title="Beyond the Basics of Using AWS S3 in CFML: Use Lifecycle Rules to Automatically Delete Files After a Period of Time" /><published>2020-06-22T13:08:00-04:00</published><updated>2020-06-22T13:08:00-04:00</updated><id>https://brianklaas.net/aws/coldfusion/2020/06/22/Beyond-Basics-S3-Lifecycle-Rules-Deletion</id><content type="html" xml:base="https://brianklaas.net/aws/coldfusion/2020/06/22/Beyond-Basics-S3-Lifecycle-Rules-Deletion.html">&lt;p&gt;In &lt;a href=&quot;https://brianklaas.net/aws/coldfusion/2020/06/16/Beyond-Basics-S3-Lifecycle-Rules.html&quot;&gt;the last post in this series&lt;/a&gt;, we looked at Lifecycle Rules in S3, how they worked, and how you can use them to save money by automatically moving less-frequently used files to different (and cheaper) storage classes. There’s another powerful aspect to Lifecycle Rules that can save you money: automatically deleting files after a specified period of time.&lt;/p&gt;

&lt;p&gt;Many of the files that are added to S3 buckets are never used after a brief, initial period of time. Many companies put all of their log files in S3. Are those log files valuable after data analysis is complete? Are the storage costs worth the price after 180 days? After 365? Are there regulatory or compliance reasons to not store user-generated data for a long period of time?&lt;/p&gt;

&lt;p&gt;Whatever the reason, do you want to do the work of tracking every file in S3 and then running tasks to determine if the file is ready for deletion? Wouldn’t it be nice if all of that could be handled transparently for you? With S3 &lt;em&gt;expiration actions&lt;/em&gt;, you don’t have to do this work. Expiration actions are a type of Lifecycle Rule that tells S3 to automatically delete a file in a bucket after a specified period of time.&lt;/p&gt;

&lt;h2 id=&quot;enabling-expiration-actions-in-cfml&quot;&gt;Enabling Expiration Actions in CFML&lt;/h2&gt;

&lt;p&gt;The process of enabling expiration actions is the same as enabling transition actions. The same steps for setting up transition actions apply when setting up expiration actions. As always, the full code for this and all of my demos can be found in my &lt;a href=&quot;https://github.com/brianklaas/awsPlaybox&quot;&gt;AWSPlaybox GitHub repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you haven’t reviewed the last post to &lt;a href=&quot;https://brianklaas.net/aws/coldfusion/2020/06/16/Beyond-Basics-S3-Lifecycle-Rules.html&quot;&gt;see the steps required in setting up transition actions&lt;/a&gt;, please do so as I will not repeat them here.&lt;/p&gt;

&lt;p&gt;The CFML code for enabling an expiration action is as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;bucketLifecycleConfig&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;CreateObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;com.amazonaws.services.s3.model.BucketLifecycleConfiguration&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;rule&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;CreateObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;com.amazonaws.services.s3.model.BucketLifecycleConfiguration$Rule&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// The rule Id just helps you to identify the purpose of the rule in plain text&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;rule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Delete objects after 90 days&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;rule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setExpirationInDays&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;90&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Rules must be set to ENABLED to actually function on the bucket&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;rule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bucketLifecycleConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ENABLED&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;bucketLifecycleConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setRules&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;s3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setBucketLifecycleConfiguration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;s3BucketName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bucketLifecycleConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This code is a bit simpler than the code for transition actions, because we’re not enabling any transitions. We’re simply setting an expiration action that applies to every file in the bucket. In this case, any file in the bucket will be automatically deleted after 90 days.&lt;/p&gt;

&lt;p&gt;You can combine transition actions and expiration actions in the same rule. You can create a rule that says “Move files from S3 standard to S3 One Zone Infrequent Access after 90 days, and delete all files after 180 days.” That’s exactly what the example code in the &lt;a href=&quot;https://github.com/brianklaas/awsPlaybox&quot;&gt;AWS Playbox app&lt;/a&gt; does.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://brianklaas.net/aws/coldfusion/2020/06/16/Beyond-Basics-S3-Lifecycle-Rules.html&quot;&gt;As explained in the post on transition actions&lt;/a&gt;, you can only have one rule set that applies to &lt;em&gt;all&lt;/em&gt; files in a bucket. You can have multiple filters based on object path prefixes or tags in a single bucket, and any combination of transition and expiration actions in those filters.&lt;/p&gt;

&lt;p&gt;Lifecycle Rules are a powerful way to reduce your overall S3 costs. If you’re storing more than a few hundred gigabytes of data in S3, I encourage you to start using them. As always, if you have any questions about this, feel free to &lt;a href=&quot;https://twitter.com/brian_klaas&quot;&gt;message me on the Twitter&lt;/a&gt;.&lt;/p&gt;</content><author><name></name></author><category term="AWS" /><category term="ColdFusion" /><summary type="html">In the last post in this series, we looked at Lifecycle Rules in S3, how they worked, and how you can use them to save money by automatically moving less-frequently used files to different (and cheaper) storage classes. There’s another powerful aspect to Lifecycle Rules that can save you money: automatically deleting files after a specified period of time.</summary></entry><entry><title type="html">Beyond the Basics of Using AWS S3 in CFML: Use Lifecycle Rules to Move Files Into Different Storage Classes</title><link href="https://brianklaas.net/aws/coldfusion/2020/06/16/Beyond-Basics-S3-Lifecycle-Rules.html" rel="alternate" type="text/html" title="Beyond the Basics of Using AWS S3 in CFML: Use Lifecycle Rules to Move Files Into Different Storage Classes" /><published>2020-06-16T13:48:00-04:00</published><updated>2020-06-16T13:48:00-04:00</updated><id>https://brianklaas.net/aws/coldfusion/2020/06/16/Beyond-Basics-S3-Lifecycle-Rules</id><content type="html" xml:base="https://brianklaas.net/aws/coldfusion/2020/06/16/Beyond-Basics-S3-Lifecycle-Rules.html">&lt;p&gt;In my last post in this series, we looked at &lt;a href=&quot;https://brianklaas.net/aws/coldfusion/2020/06/02/Beyond-Basics-S3-Storage-Classes.html&quot;&gt;using different storage classes in S3 via CFML to save money&lt;/a&gt; on long-term storage costs. The use case for that blog post assumed you knew the utilization pattern for the files you uploaded. They would either be very busy files, files that were accessed occasionally, or files that were accessed rarely. What happens, though, when file acess moves over time from frequently access to only occasional access? Wouldn’t it be nice if S3 would automatically move those files from a more expensive storage class with the fastest response time to a storage class where response times were a few miliseconds longer, but cost half the price?&lt;/p&gt;

&lt;p&gt;S3 provides &lt;a href=&quot;https://docs.aws.amazon.com/AmazonS3/latest/dev/object-lifecycle-mgmt.html&quot;&gt;lifecycle rules&lt;/a&gt; to do exactly that.&lt;/p&gt;

&lt;h2 id=&quot;how-lifecycle-rules-work&quot;&gt;How Lifecycle Rules Work&lt;/h2&gt;

&lt;p&gt;You can only apply lifecycle rules to a whole bucket, but you can define filters in these rules so that only specific files in the bucket are affected by the lifecycle rule. There are two types of lifecycle rules that can be applied to a S3 bucket. There are &lt;em&gt;transition actions&lt;/em&gt;, which we’ll look at now, and &lt;em&gt;expiration actions&lt;/em&gt;, which we will look at in a future post.&lt;/p&gt;

&lt;p&gt;Transition actions tell S3 to &lt;em&gt;transition&lt;/em&gt; files from one storage class to another when certain criteria are met. For example, you can tell S3 to automatically move files to infrequent access, one zone storage 30 days after creation. You can tell S3 to automatically move files to Glacier deep archive after 365 days. This not only can save you money over time (do you really need the drafts of the 2014 annual report to stay in S3 standard storage?), but it also automates determining which files should be moved and when they should be moved.&lt;/p&gt;

&lt;h2 id=&quot;intelligent-tiering-vs-transition-actions&quot;&gt;Intelligent Tiering vs. Transition Actions&lt;/h2&gt;

&lt;p&gt;S3 does offer a storage class called “&lt;a href=&quot;https://aws.amazon.com/s3/storage-classes/#Unknown_or_changing_access&quot;&gt;intelligent tiering&lt;/a&gt;.” This tier of storage looks at access patterns for every file in this storage class, and automatically moves files from S3 standard to S3 infrequent access if the file has not been accessed in the last 30 days. The advantage to intelligent tiering is that if a file remains frequently accessed after 30 days, it will stay in the S3 standard class. Transition actions ignore &lt;em&gt;individual&lt;/em&gt; file access patterns. Transition actions are apply to all files in the bucket, regardless of individual file access patterns. If your lifecycle rule says to transition all files in the bucket from S3 standard to S3 infrequent access after 30 days, that’s going to happen at the 30 day mark even if the file is still frequently accessed.&lt;/p&gt;

&lt;p&gt;Intelligent tiering does have an overhead charge of $0.0025 per 1,000 objects monitored. This can add up over time, and may not be the best choice if your general access patterns for files in a bucket are well known. Intelligent tiering only manages files over 128KB in size, so this is not a good approach for small log files. (It’s also important to note that S3 standard infrequent access and S3 one zone infrequent access storage both have a minimum billable object size of 128KB.)&lt;/p&gt;

&lt;h2 id=&quot;enabling-lifecycle-rules-in-cfml&quot;&gt;Enabling Lifecycle Rules in CFML&lt;/h2&gt;

&lt;p&gt;If you decide that a lifecycle rule is the best way to automate changing storage classes for your files in S3, you can manage those rules (and change or delete them) from within your CFML applications. As always, the full code for this and all of my demos can be found in my &lt;a href=&quot;https://github.com/brianklaas/awsPlaybox&quot;&gt;AWSPlaybox GitHub repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are five steps to enabling lifecycle rules via the AWS Java SDK:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Create a BucketLifecycleConfiguration object to apply to the whole bucket&lt;/li&gt;
  &lt;li&gt;Create a BucketLifecycleConfiguration$Rule object that defines a transition rule&lt;/li&gt;
  &lt;li&gt;Create a BucketLifecycleConfiguration$Transition object that specifies the storage class to change to after a specified period&lt;/li&gt;
  &lt;li&gt;Enable the rule&lt;/li&gt;
  &lt;li&gt;Apply the BucketLifecycleConfiguration to the bucket&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s look at this in code:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;bucketLifecycleConfig&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;CreateObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;com.amazonaws.services.s3.model.BucketLifecycleConfiguration&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;rule&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;CreateObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;com.amazonaws.services.s3.model.BucketLifecycleConfiguration$Rule&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// The rule Id just helps you to identify the purpose of the rule in plain text&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;rule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Move to One Zone Infrequent Access after 30 days&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;storageClassObj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;CreateObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;com.amazonaws.services.s3.model.StorageClass&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;transition&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;CreateObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;com.amazonaws.services.s3.model.BucketLifecycleConfiguration$Transition&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;withDays&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;withStorageClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;storageClassObj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;valueOf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;OneZoneInfrequentAccess&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// setTransitions expects a Java List, which is just a CFML array&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;rule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setTransitions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;transition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Rules must be set to ENABLED to actually function on the bucket&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;rule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bucketLifecycleConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ENABLED&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;bucketLifecycleConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setRules&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;s3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setBucketLifecycleConfiguration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;s3BucketName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bucketLifecycleConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The code follows the list of steps above, but there are a few points that bear explanation:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;If you’re wondering what’s up with the $ in some of the Java class names, that’s how you instantiate nested Java classes in CFML. The Rule and Transition objects are nested classes of the BucketLifecycleConfiguration object in the AWS Java SDK, so you reference them with the $ in the class name. A big thanks to &lt;a href=&quot;https://www.bennadel.com/blog/1370-ask-ben-instantiating-nested-java-classes-in-coldfusion.htm&quot;&gt;Ben Nadel for documeting that tip&lt;/a&gt;!&lt;/li&gt;
  &lt;li&gt;Rules are not automatically enabled when created or applied to a Transition object. They must be explicity ENABLEd to take affect. (This means you can also disable them as needed without deleting them off a bucket lifecycle configuration.)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;rules-and-filters&quot;&gt;Rules and Filters&lt;/h2&gt;

&lt;p&gt;While it’s easy to create a transition action for a whole bucket, you can only have &lt;em&gt;one&lt;/em&gt; “all files” transition action per bucket. That is: you can only have one rule that applies to &lt;em&gt;every file&lt;/em&gt; in the bucket. You can have many transition actions per bucket, but they must be defined with individual rules that apply &lt;em&gt;filters&lt;/em&gt; to the files affected by the transition actions. You can filter by an object key prefix (the “path” to the object in the bucket), known as a &lt;a href=&quot;https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/model/lifecycle/LifecyclePrefixPredicate.html&quot;&gt;Prefix Predicate&lt;/a&gt;, or a &lt;a href=&quot;https://docs.aws.amazon.com/AmazonS3/latest/dev/object-tagging.html&quot;&gt;tag&lt;/a&gt; that’s applied to a file, known as a &lt;a href=&quot;https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/model/lifecycle/LifecycleTagPredicate.html&quot;&gt;Tag Predicate&lt;/a&gt;. I’ll cover applying tags to files when you upload them to S3 in a future post.&lt;/p&gt;

&lt;p&gt;Using both prefix predicates and tag predicates, you can have several rules for any given bucket and be specific about when different kinds of files in different parts of a bucket are automatically transitioned from one storage class to another. This is useful when you have long-established buckets with a lot of data and don’t want to incur the cost (and overhead) of moving the files into separate buckets to enforce different transition actions.&lt;/p&gt;

&lt;p&gt;In the next post in this series, we’ll look at expiration actions, which are perfect for handling files with short lifespans, like log files. As always, if you have any questions about this, feel free to &lt;a href=&quot;https://twitter.com/brian_klaas&quot;&gt;message me on the Twitter&lt;/a&gt;.&lt;/p&gt;</content><author><name></name></author><category term="AWS" /><category term="ColdFusion" /><summary type="html">In my last post in this series, we looked at using different storage classes in S3 via CFML to save money on long-term storage costs. The use case for that blog post assumed you knew the utilization pattern for the files you uploaded. They would either be very busy files, files that were accessed occasionally, or files that were accessed rarely. What happens, though, when file acess moves over time from frequently access to only occasional access? Wouldn’t it be nice if S3 would automatically move those files from a more expensive storage class with the fastest response time to a storage class where response times were a few miliseconds longer, but cost half the price?</summary></entry></feed>