<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Alessio Piergiacomi on Medium]]></title>
        <description><![CDATA[Stories by Alessio Piergiacomi on Medium]]></description>
        <link>https://medium.com/@alessiopiergiacomi?source=rss-ea1aff83a909------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/2*rMndsJdWe-kStLoKwnYsxA.jpeg</url>
            <title>Stories by Alessio Piergiacomi on Medium</title>
            <link>https://medium.com/@alessiopiergiacomi?source=rss-ea1aff83a909------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 11:38:24 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@alessiopiergiacomi/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Multi-threaded Fizz buzz]]></title>
            <link>https://medium.com/@alessiopiergiacomi/multi-threaded-fizz-buzz-29c3046c03e0?source=rss-ea1aff83a909------2</link>
            <guid isPermaLink="false">https://medium.com/p/29c3046c03e0</guid>
            <category><![CDATA[interview-questions]]></category>
            <category><![CDATA[concurrency]]></category>
            <category><![CDATA[fizzbuzz]]></category>
            <category><![CDATA[leetcode]]></category>
            <dc:creator><![CDATA[Alessio Piergiacomi]]></dc:creator>
            <pubDate>Sun, 23 Aug 2020 21:39:35 GMT</pubDate>
            <atom:updated>2020-08-23T21:50:31.122Z</atom:updated>
            <content:encoded><![CDATA[<p>I have recently stumbled upon the <a href="https://leetcode.com/problems/fizz-buzz-multithreaded/">multi-threaded version of the classic fizz buzz problem on Leetcode</a>: (unsurprisingly) introducing concurrency adds some depth to the usually uninteresting fizz buzz problem.</p><p>There are 4 different threads, each one will invoke exactly once one of the four functions fizz, buzz, fizzbuzz and number and we want them to produce the output in the expected order. For more details please refer to the <a href="https://leetcode.com/problems/fizz-buzz-multithreaded/">Leetcode problem description</a>.</p><p>I have tried to solve the problem in different ways, using different python concurrency primitives (sorry I haven’t realised until today how bad the syntax highlighting is in Medium).</p><h4><strong>Solution 1: Busy waiting with a lock</strong></h4><p>We have 4 distinct loops, but because of the mutually exclusive if conditions, only one will increase the shared counter variable at any given time. They keep spinning all the time, until it’s “their turn” to increment the counter value and print an output.</p><p>You might think that given only one of the if conditions evaluates to true for any given counter value then we don’t need the lock at all. Unfortunately that is not the case: at the end of the loop you can have a value &gt; n printed despite self.counter &gt;= n, as the condition might be evaluated before the counter is incremented in a different thread.</p><pre>from threading import Lock<br>class FizzBuzz:<br>    def __init__(self, n: int):<br>        self.n = n<br>        self.counter = 1<br>        self.lock = Lock()</pre><pre>    def fizz(self, printFizz):<br>     while self.counter &lt;= self.n:<br>            with self.lock:<br>                if self.counter &lt;= self.n and self.counter %3 == 0 and self.counter %5 != 0:<br>                    printFizz()<br>                    self.counter +=1</pre><pre>    def buzz(self, printBuzz):<br>        while self.counter &lt;= self.n:<br>            with self.lock:<br>                if self.counter &lt;= self.n and self.counter %3 != 0 and self.counter %5 == 0:<br>                    printBuzz()<br>                    self.counter +=1</pre><pre>    def fizzbuzz(self, printFizzBuzz):<br>        while self.counter &lt;= self.n:<br>            with self.lock:<br>                if self.counter &lt;= self.n and self.counter % 15 == 0:<br>                    printFizzBuzz()<br>                    self.counter +=1</pre><pre>    def number(self, printNumber):        <br>        while self.counter &lt;= self.n:<br>            with self.lock:<br>                if self.counter &lt;= self.n and self.counter %3 &gt; 0 and self.counter %5 &gt; 0:<br>                    printNumber(self.counter)<br>                    self.counter +=1</pre><h4>Solution 2: a single thread orchestrating the other 3 with three conditions</h4><p>fizz() , buzz() and fizzbuzz() threads are waiting and activated in turn by the number() thread, which orchestrates the whole program logic by notifying to a thread using its dedicated condition and then waiting for a signal on the same condition once the unblocked thread has printed and increased the counter. After n has been reached, the number() threads must take care of unblocking all the waiting threads despite it’s not their turn, just to let them (and the program) terminate. Compared to the solution 1, this is way faster, as doesn’t involve <a href="https://en.wikipedia.org/wiki/Busy_waiting">busy waiting</a>.</p><pre>import threading<br>class FizzBuzz:<br>    def __init__(self, n: int):<br>        self.n = n<br>        self.counter = 1<br>        self.cond_fizz = threading.Condition()<br>        self.cond_buzz = threading.Condition()<br>        self.cond_fizzbuzz = threading.Condition()</pre><pre>    def fizz(self, printFizz):<br>        while True:<br>            with self.cond_fizz:<br>                self.cond_fizz.wait()<br>                <br>                if self.stop_condition():<br>                    break<br>                <br>                printFizz()<br>                self.counter +=1<br>                self.cond_fizz.notify()</pre><pre>    def buzz(self, printBuzz):<br>        while True:<br>            with self.cond_buzz:<br>                self.cond_buzz.wait()                <br>                <br>                if self.stop_condition():<br>                    break<br>                <br>                printBuzz()<br>                self.counter +=1     <br>                self.cond_buzz.notify()               </pre><pre>    def fizzbuzz(self, printFizzBuzz):<br>        while True:<br>            with self.cond_fizzbuzz:<br>                self.cond_fizzbuzz.wait()            <br>                if self.stop_condition():<br>                    break<br>                printFizzBuzz()<br>                self.counter +=1<br>                self.cond_fizzbuzz.notify()            <br>       <br>    def number(self, printNumber):        <br>        while not self.stop_condition():            <br>            <br>            if self.counter %3 &gt; 0 and self.counter %5 &gt; 0:<br>                printNumber(self.counter)<br>                self.counter +=1<br>            elif self.counter % 3 == 0 and self.counter % 5 &gt; 0:<br>                with self.cond_fizz:<br>                    self.cond_fizz.notify()                    <br>                    self.cond_fizz.wait() # waiting to get back control<br>            elif self.counter % 3 &gt; 0 and self.counter % 5 == 0:<br>                with self.cond_buzz:<br>                    self.cond_buzz.notify()<br>                    self.cond_buzz.wait()<br>            else: # fizzbuzz<br>                with self.cond_fizzbuzz:<br>                    self.cond_fizzbuzz.notify()<br>                    self.cond_fizzbuzz.wait()<br>                    <br>        self.terminate_all_threads()<br>                    <br>    def stop_condition(self):<br>        return self.counter &gt; self.n# all threads are waiting<br>    def terminate_all_threads(self): <br>        with self.cond_fizzbuzz:<br>            self.cond_fizzbuzz.notify()<br>        with self.cond_fizz:<br>            self.cond_fizz.notify()    <br>        with self.cond_buzz:<br>            self.cond_buzz.notify()</pre><h4>Solution 3: Having the four threads passing control each other</h4><p>Unlike Solution 2, here we have some kind of “decentralised” choreography: it’s not anymore just the number() thread containing all the logic, but each thread, once in execution, establishes what thread will be unblocked next, and then proceeds to unblocks it. Again, once we reach the stop condition we need some termination-specific code to unblock all the threads and let the threads (and the program) to terminate.</p><pre>import threading<br>class FizzBuzz:<br>    def __init__(self, n: int):<br>        self.n = n<br>        self.counter = 1<br>        self.fizz_event = threading.Event()<br>        self.buzz_event = threading.Event()<br>        self.fb_event = threading.Event()<br>        self.number_event = threading.Event()<br>        self.number_event.set()</pre><pre>    def fizz(self, printFizz):</pre><pre>        while True:<br>            self.fizz_event.wait()<br>                <br>            if self.stop_condition():<br>                self.stop_all()<br>                break<br>                <br>            printFizz()<br>            self.counter +=1<br>            <br>            self.fizz_event.clear()<br>            self.trigger_next_event()</pre><pre>    def buzz(self, printBuzz):<br>        while True:<br>            self.buzz_event.wait()<br>                <br>            if self.stop_condition():<br>                self.stop_all()<br>                break<br>                <br>            printBuzz()<br>            self.counter +=1     <br>            <br>            self.buzz_event.clear()<br>            self.trigger_next_event()<br>                <br>    def fizzbuzz(self, printFizzBuzz):<br>        while True:<br>            <br>            self.fb_event.wait()<br>            if self.stop_condition():<br>                self.stop_all()<br>                break</pre><pre>            printFizzBuzz()<br>            self.counter +=1<br>            <br>            self.fb_event.clear()<br>            self.trigger_next_event()<br>    def number(self, printNumber):        <br>        while True:            <br>            self.number_event.wait()<br>            <br>            if self.stop_condition():<br>                self.stop_all()<br>                break</pre><pre>            printNumber(self.counter)<br>            self.counter +=1<br>            <br>            self.number_event.clear()<br>            self.trigger_next_event()                            <br>        <br>                    <br>    def stop_condition(self):<br>        return self.counter &gt; self.n    <br>            <br>    def stop_all(self):<br>        self.number_event.set()<br>        self.fizz_event.set()<br>        self.buzz_event.set()<br>        self.fb_event.set()<br>            <br>    def trigger_next_event(self):<br>        if self.counter %3 &gt; 0 and self.counter %5 &gt; 0:<br>            self.number_event.set()<br>        elif self.counter % 3 == 0 and self.counter % 5 &gt; 0:<br>            self.fizz_event.set()<br>        elif self.counter % 3 &gt; 0 and self.counter % 5 == 0:<br>            self.buzz_event.set()<br>        else: # fizzbuzz<br>            self.fb_event.set()</pre><h4><strong>Solution 4: Using a single condition, with every threads checking on a different predicate whenever we send a signal to all the threads waiting.</strong></h4><p>Every threads wait on a condition for a specific predicate self.counter == &lt;next_number_this_threads_must_print&gt;. When the predicate is true and a thread is unblocked, it prints and then send a signal on the condition to all the other threads. We are guaranteed that one of the threads will have its predicate evaluating to true, so one thread will print something, increment the counter and then notify again to all the threads. This is the faster solution described in this post.</p><pre>import threading</pre><pre>class FizzBuzz:<br>    def __init__(self, n: int):<br>        self.n = n<br>        self.counter = 1<br>        self.cond = threading.Condition()</pre><pre>    def is_fizz(self):<br>        return self.counter % 3 == 0 and self.counter % 5 != 0</pre><pre>    def fizz(self, printFizz):<br>        while self.n &gt;= 3:<br>            with self.cond:<br>                self.cond.wait_for(self.is_fizz)</pre><pre>                printFizz()<br>                self.counter += 1</pre><pre>                self.cond.notify_all()</pre><pre>            if self.counter + 2 &gt; self.n or ((self.counter + 2) % 5 == 0 and self.counter + 5 &gt; self.n):<br>                break</pre><pre>    def is_buzz(self):<br>        return self.counter % 3 != 0 and self.counter % 5 == 0</pre><pre>    def buzz(self, printBuzz):<br>        while self.n &gt;= 5:<br>            with self.cond:<br>                self.cond.wait_for(self.is_buzz)</pre><pre>                printBuzz()<br>                self.counter += 1</pre><pre>                self.cond.notify_all()</pre><pre>            if self.counter + 4 &gt; self.n or ((self.counter + 4) % 3 == 0 and self.counter + 9 &gt; self.n):<br>                break</pre><pre>    def is_fb(self):<br>        return self.counter % 3 == 0 and self.counter % 5 == 0</pre><pre>    def fizzbuzz(self, printFizzBuzz):<br>        while self.n &gt;= 15:</pre><pre>            with self.cond:<br>                self.cond.wait_for(self.is_fb)</pre><pre>                printFizzBuzz()<br>                self.counter += 1</pre><pre>                self.cond.notify_all()</pre><pre>             if self.counter + 14 &gt; self.n:<br>                 break</pre><pre>    def is_nothing(self):<br>        return self.counter % 3 &gt; 0 and self.counter % 5 &gt; 0</pre><pre>    def number(self, printNumber):<br>        while True:<br>            with self.cond:<br>                self.cond.wait_for(self.is_nothing)</pre><pre>            printNumber(self.counter)<br>                self.counter += 1</pre><pre>            self.cond.notify_all()</pre><pre>            # find next number call<br>            i = self.counter<br>            while i % 3 == 0 or i % 5 == 0:<br>                i += 1<br>            # this is the last number printed<br>            if i &gt; self.n:<br>                break</pre><h4><strong>Solution 5: Using barriers</strong></h4><p>In this solution each thread has its own loop 1 to n, and we make sure we advance the loops in sync by using a barrier, waiting for the 4 threads to reach the barrier before unblocking all the threads. At that point the loop will continue, the next number will be processed by all the 4 threads (only one thread will eventually print something), and the program will wait again for all the threads to reach the barrier, and so on.</p><pre>class FizzBuzz:<br>    def __init__(self, n: int):<br>        self.n = n<br>        self.barrier = threading.Barrier(4)</pre><pre>   def fizz(self, printFizz):<br>        for i in range(1, self.n+1):<br>            if i % 3 == 0 and i % 5 != 0:<br>                printFizz()</pre><pre>            self.barrier.wait()</pre><pre>   def buzz(self, printBuzz):<br>        for i in range(1, self.n+1):<br>            if i % 3 != 0 and i % 5 == 0:<br>                printBuzz()</pre><pre>            self.barrier.wait()</pre><pre>    def fizzbuzz(self, printFizzBuzz):<br>        for i in range(1, self.n+1):<br>            if i % 15 == 0:<br>                printFizzBuzz()</pre><pre>            self.barrier.wait()</pre><pre>    def number(self, printNumber):<br>        for i in range(1, self.n+1):</pre><pre>            if i % 3 &gt; 0 and i % 5 &gt; 0:<br>                printNumber(i)</pre><pre>            self.barrier.wait()</pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=29c3046c03e0" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Certification: Mission accomplished]]></title>
            <link>https://medium.com/@alessiopiergiacomi/certification-mission-accomplished-616dd43efcf6?source=rss-ea1aff83a909------2</link>
            <guid isPermaLink="false">https://medium.com/p/616dd43efcf6</guid>
            <category><![CDATA[aws-certified-architect]]></category>
            <category><![CDATA[aws-certified]]></category>
            <category><![CDATA[aws-certification]]></category>
            <dc:creator><![CDATA[Alessio Piergiacomi]]></dc:creator>
            <pubDate>Thu, 28 May 2020 18:37:11 GMT</pubDate>
            <atom:updated>2020-05-28T18:37:11.641Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/978/1*Aw_8lWiNibEIbMu_embF8Q.jpeg" /></figure><p>I’ve stopped writing updates on my AWS Solution Architect Professional certification prep, but I kept studying... and managed to pass the exam two days ago 🎉.</p><p>Because of COVID-19 all the exams were taking place online, with some cumbersome software which skyrocketed the cpu usage on my old MacBook Air Mid 2011 to <em>the point that I was afraid my laptop would have eventually shut down due to overheating</em> 🤷‍♂️. The software was recording you via webcam, not sure if the cpu usage was caused by some sophisticated software detecting if I was doing something dodgy or if the software was just very poorly written and the my behaviour was checked by a human behind the scenes…</p><p>Anyway, in the online proctored exams you’re suggested to login 30 mins before the exam start time to get everything set up. <strong>Too bad the certification platform actually had an outage until 2 minutes before my exam start time</strong> 😬 (it was a multiple hours outage, I wasn’t sure I’d be able to take the exam until the very last minute).</p><h3>Alessio Piergiacomi on Twitter</h3><p>Quite ironic from someone delivering training/exams on how to build highly available architectures to have a 4+ hours complete outage</p><p>A relevant difference between the on-site and online exams (<em>or at least between how the on-site exam was set up 3 years ago and how it is done online today</em>) is a<strong> set of restrictions </strong>which make the exam even harder from a body-mind perspective, for example:</p><ul><li>you can’t drink water during the exam, or you get immediately disqualified</li><li>you can’t stand up and stretch during the exam, or you get immediately disqualified</li></ul><p>So the online candidate has to sit for 180 minutes straight (or 210 with the extra 30 minutes for non-native English speakers), without drinking anything, while 75 moderately long questions are shot at them.</p><p>I did close the window to avoid outside noise, but being my room exposed to the sun during the exam this caused the temperature to increase over time, as my dehydration, making focusing on the questions a bit harder.</p><p>I can’t really talk much of the contents of the exams: it was covering a lot topics (but nothing really surprising, having prepared following the course I described <a href="https://medium.com/@alessiopiergiacomi/road-to-aws-certification-pivot-ddcfb2f25d47">here</a>) and often tricky (some questions had 2 completely reasonable multiple choice answers out of 4, and you had to find out which one was the “most correct”), but <em>the hard part was really the not optimal conditions in which I took the exam</em>.</p><p>I ended up passing with 86% (75% was required for passing), but I feel like the exam tested too much your ability to keep calm and your mental toughness (breathing techniques and checking the time definitely helped me there).</p><p><strong>My final 2 cents: personally I would change the format of the exam by reducing the number of questions and the duration of the exam, and maybe balancing the exam toughness by increasing the % required to pass. I think such measures would make the exam more about AWS knowledge and less about your speed reading/time management/mental toughness game.</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=616dd43efcf6" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Road to AWS Certification: goodbye daily diary with study details]]></title>
            <link>https://medium.com/@alessiopiergiacomi/road-to-aws-certification-goodbye-daily-diary-with-study-details-fc7869a62ce9?source=rss-ea1aff83a909------2</link>
            <guid isPermaLink="false">https://medium.com/p/fc7869a62ce9</guid>
            <dc:creator><![CDATA[Alessio Piergiacomi]]></dc:creator>
            <pubDate>Wed, 15 Apr 2020 19:35:32 GMT</pubDate>
            <atom:updated>2020-04-15T19:35:32.797Z</atom:updated>
            <content:encoded><![CDATA[<p>Third post of the day 😬, but I have also realized the scope of the exam is broader than I anticipated, so in order to achieve the certification in a reasonable span of time,<strong> I have decided to give up on writing a study diary on medium.</strong></p><p>While useful, it requires me to proof read and “refactor” the text, and ends up subtracting quite a substantial amount of time from the study.</p><p>I’ll keep doing the daily check-ins on the exam preparation to keep me accountable to push with the study, but I won’t add any technical details on the topics of the day, I’ll leave the technical details to my private (unrevised) notes.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=fc7869a62ce9" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Road to AWS Certification: pivot]]></title>
            <link>https://medium.com/@alessiopiergiacomi/road-to-aws-certification-pivot-ddcfb2f25d47?source=rss-ea1aff83a909------2</link>
            <guid isPermaLink="false">https://medium.com/p/ddcfb2f25d47</guid>
            <category><![CDATA[aws-certification]]></category>
            <category><![CDATA[acloudguru]]></category>
            <dc:creator><![CDATA[Alessio Piergiacomi]]></dc:creator>
            <pubDate>Wed, 15 Apr 2020 19:28:59 GMT</pubDate>
            <atom:updated>2020-04-15T19:31:15.336Z</atom:updated>
            <content:encoded><![CDATA[<p>Change of strategy in my preparation for the AWS Certified Solutions Architect Professional: I have come to the realization that the <strong>cloud guru course is not just succinct by leaving students to individual study on whitepapers and re:Invent videos, I think <em>the execution of the course is just sloppy</em></strong>, not worth the money.</p><p>I would rather have a course which integrates the important bits from the Whitepapers rather than a course that says “go and read them yourself”. So I’ve looked for some opinions around and settled for the <a href="https://www.udemy.com/course/amazon-certified-solutions-architect-professional/">DolfinEd Udemy course</a>, which is more expensive than the acloud.guru, but apparently more complete.</p><p>I’ve started the new course, which starts with a AWS Certified Solution Architect Associate exam simulation, to see where you are.</p><p>That took pretty much my whole slot of study for the day, the exam simulation alone took 2+ hours 😃.</p><h4><strong>What I learned from the CSAA exam simulation</strong></h4><p>I passed the exam simulation (77%, 75% was required), but I’ve realized I have some gaps I’ll need to fix before attempting the Pro Exam. In particular the gaps regarded:</p><ul><li>what’s the retrieval process from S3 Glacier (i.e. temporarily storing for X days on S3 Reduced Redundancy Storage)</li><li>diffrent types of AD (AWS Directory Service &gt; 5000 users with trust relationship with the on-premise AD, Simple AD &lt; 5000 users, AD Connector with a gateway that redirects directory requests to your on-premise Microsoft AD without any caching)</li><li>Redis now supports cluster mode to scale more with sharding over more primary nodes.</li><li>Virtual Interfaces (VIF) for Direct Connect: private VIF for VPC entry points or public VIF for access to AWS services or transit VIF for AWS Transite Gateway hub</li><li>ASG: can span multi-AZ (and auto re-balance), health check grace period after startup is 300 second by default, different auto-scaling policies</li></ul><p>Different auto-scaling policies in particular was a topic I completely removed off my head after the certification I took 3 years ago (now I start remembering bits and pieces). There are 4 types of policies:</p><ul><li>Manual scaling: manually change ASC min/desired/max</li><li>Cyclic (schedule based) scaling, for predictable load changes</li><li>On-demand/Dynamic (event based) scaling: in response to a CW alarm (CPU utilization, memory, network I/O) or an event. You need a scale-out and scale-in policy configured. You can have a cool down timer to expire before responding to more alarms (with simple scaling) or a warm-up timer which sets the time it takes for an instance to be ready and contribute to the watched metric</li><li>Predictive scaling (both on demand but also tries to predict future traffic based on daily and weekly trends, using Machine Learning).</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ddcfb2f25d47" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Road to AWS Certification: Route53 and Load Balancers]]></title>
            <link>https://medium.com/@alessiopiergiacomi/road-to-aws-certification-route53-and-load-balancers-a83666621deb?source=rss-ea1aff83a909------2</link>
            <guid isPermaLink="false">https://medium.com/p/a83666621deb</guid>
            <category><![CDATA[aws-certification]]></category>
            <dc:creator><![CDATA[Alessio Piergiacomi]]></dc:creator>
            <pubDate>Wed, 15 Apr 2020 18:31:43 GMT</pubDate>
            <atom:updated>2020-04-15T18:31:43.949Z</atom:updated>
            <content:encoded><![CDATA[<p>Another post of my study-diary series in preparation of the AWS Certified Professional Exam.</p><h3>DNS and Route53</h3><h4>DNS</h4><p>Naming system for computers, services or other resources connected to the internet or a private network. It is hierarchical: when you try to resolve <em>google.it </em>you first go to your<em> local resolving server</em>, if it already knows the mapping it returns you the IP, otherwise it goes to the top-level domain name server for <em>the .it </em>top level domain, which gives you the address of the content server who actually contains the record for google.it, then query it and finally obtain the IP address.</p><p>The mappings are stored as set of resource records (RR), characterised by a type, a name, RDATA, TTL and other fields less relevant in this context.</p><p>Type defines the type of mapping name -&gt; RDATAcontained in the record. Examples of type include:</p><ul><li><strong>A: </strong>address record, maps a name to an IPv4 address</li><li><strong>AAAA</strong>: IPv6 address record</li><li><strong>CNAME</strong>: canonical name record, maps an hostname to another hostname</li><li><strong>MX</strong>: mail exchange record</li><li><strong>NS</strong>: name server record, they tell you what content name server(s) is authorattive to a particular zone or domain name</li></ul><h4>Route53</h4><p>Route53 is AWS’s managed DNS service. DNS records are grouped into “hosted zones”, collection of records that can be managed together, belonging to a single parent domain (e.g. alessio.engineer) .</p><p>Route53 does not support all the DNS record types (for example it doesn’t supprot DNSSEC related records, where DNSSEC is a protocol to secure the DNS traffic). It supports a custom type of record called <strong>alias</strong>, which is a mapping from a name to an AWS resource such as ELB, CF, API Gateway, S3 bucket).</p><p>Route53 has several DNS <a href="https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy.html">routing policies</a>:</p><ul><li><strong>Simple routing policy</strong> – Use for a single resource that performs a given function for your domain, for example, a web server that serves content for the example.com website.</li><li><strong>Failover routing policy</strong> – Use when you want to configure active-passive failover.</li><li><strong>Geolocation routing policy</strong> – Use when you want to route traffic based on the location of your users.</li><li><strong>Geoproximity routing policy</strong> – Use when you want to route traffic based on the location of your resources and, optionally, shift traffic from resources in one location to resources in another (assigning some bias, e.g. be biased towards assigning more traffic from Spain to the Dublin region and not the Frankfurt one)</li><li><strong>Latency routing policy</strong> – Use when you have resources in multiple AWS Regions and you want to route traffic to the region that provides the best latency.</li><li><strong>Multivalue answer routing policy</strong> – Use when you want Route 53 to respond to DNS queries with up to eight healthy records selected at random (very raw load balancing)</li><li><strong>Weighted routing policy</strong> – Use to route traffic to multiple resources in proportions that you specify.</li></ul><h3>Load Balancers</h3><p>Region specific, internet facing (you have hostname) or internal load balancers. They are defined within a subnet. Charged hourly + per traffic. All LB support logging API calls via AWS Cloud Trail.</p><h4>Classic Load Balancer</h4><p>Older version still around, works at both L4, and L7 (no HTTP/2 support, or HTTPS websocket support). Need at least two AZ and you need at least 8 available IP addresses (for scaling purposes). Default health check 30s (range 5–300). <em>Must have a security group</em>, controlling traffic that can reach ELB front end listener. <em>Subnet ACLs must also allow traffic to/from ELB both ways.</em></p><p>Supports session stickiness, via a special cookie.</p><p>Does not support Server Name Indication (SNI): you can upload a certificate via ACM but you can’t add multiple certificates for the same IP/port pair.</p><h4>Elastic Load Balancer</h4><p>L4 Load Balancer, supports TCP/TLS listeners for client requests and UDP traffic. Scales more (but requires a pre-warm for spikes of traffic), and has lower latencies than other ELBs.</p><p>Supports client source IP address preservation via “proxy protocol”.</p><p>Both active and passive (networks) health checks. The passive are how the targets react to connections.</p><p>Does not support sticky sessions.</p><h4>Application Load Balancer</h4><p>L7 Load Balancer, supports HTTP/2 and websockets over HTTPs. Can serve multiple application on separate fleets (target groups, characterised by a protocool and a port, they can be EC2 instances, ECS containers, IP addresses; not public internet routable ip addresses though).</p><p>When a condition is met traffic is forwarded to the associated target group. <br>Content based routing: based on the content request, route to a certain path or host.</p><p>ALB supports WAF. It also supports SNI.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a83666621deb" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Road to AWS Certification: VPCs]]></title>
            <link>https://medium.com/@alessiopiergiacomi/road-to-aws-certification-vpcs-c77f59ded19e?source=rss-ea1aff83a909------2</link>
            <guid isPermaLink="false">https://medium.com/p/c77f59ded19e</guid>
            <category><![CDATA[aws-certification]]></category>
            <category><![CDATA[vpc]]></category>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[aws-vpc]]></category>
            <dc:creator><![CDATA[Alessio Piergiacomi]]></dc:creator>
            <pubDate>Tue, 14 Apr 2020 11:30:11 GMT</pubDate>
            <atom:updated>2020-04-14T11:30:11.409Z</atom:updated>
            <content:encoded><![CDATA[<p>Fourth post in my accountability diary for the AWS Certified Architect — Professional certification study, topic of the day is networking and VPCs.</p><h3>Basic VPC concepts from the associate curriculum</h3><p>Virtual Private Clouds are “virtualized data centers”, each AWS account comes with one “<strong>Default VPC</strong>” per region, set up in order to make as easy as possible to start using EC2 instances connected to the internet; such VPC contains:</p><ul><li>65531 IP addresses ( /16 CIDR block, minus 5 reserved addresses)</li><li>one <strong>subnet </strong>per AZ (subnets can’t span multiple AZ)</li><li>one<strong> Internet Gateway</strong> (more on this below)</li><li>one <strong>route table</strong> mapping locally all the traffic within the VPC IP block and to the internet gateway all the other traffic</li><li>one <strong>Network ACL</strong> allowing<em> all the traffic (both inbound and outbound</em>) associated to all the subnets (you can associate 1 ACL to many subnets, but one subnet to a single ACL)</li><li>one <strong>Security Group </strong>allowing all traffic outbound and only inbound traffic coming from within the SG itself</li></ul><p>The “default VPC” recipe is different from the one used to create additional <strong>new VPCs</strong>. New VPCs contain:</p><ul><li>a CIDR block of IP addresses (between /16 and /28). This will be the primary block and you won’t be able to modify it later. You can still add other blocks though.</li><li>one <strong>route table</strong> mapping locally all the traffic within the VPC IP block (so no automatic mapping to an Internet Gateway, NAT Gateway or any other mean to reach the public internet — there aren’t any for this VPC)</li><li>one new <strong>Network ACL</strong> allowing<em> all the traffic (inbound and outbound</em>), associated to no subnets — there aren’t any for this VPC</li><li>one <strong>Security Group </strong>allowing all traffic outbound and only inbound traffic coming from within the Security Group itself</li></ul><h4>Security Groups and Network Access Control Lists</h4><p>NACLs area stateless component that filters the traffic in and out from a subnet.</p><p>Security Groups are stateful componenst that filter traffic in and out from an EC2 instance or an Elastic Network Interface (virtual network interface you can attach/detach to EC2 instances).</p><p><strong>Stateful vs stateless<br></strong>In this context stateless means that the component doesn’t keep track of requests coming in and out.</p><p>For example if we allow traffic in for port 80, we’ll also have to open outbound traffic to the ephemeral ports range (1025–65536, pretty much every port except the well known 1–1024 range), because that’s where the HTTP client will expect the return traffic from a web server.</p><p>As opposed to this, a stateful Security Group can achieve the same result by only enabling traffic inbound at port 80: it will recognize that an outbound request to an ephemeral port corresponds to the return traffic from the previous request and it will let it through without the need of explicit rules.</p><h4>Communicating with the internet</h4><p>There are several ways to have a VPC communicating with the internet.</p><p><strong>Internet Gateway </strong>is a fully managed (hence scalable, available, etc.) resource which you can use to access the internet in both direction from your VPC. It doesn’t sit in a specific subnet.</p><p>The <strong>NAT Gateway</strong> is another fully managed service, sitting within a public subnet (hence in a single AZ, if you want redundancy you need to have everything duplicated in a different AZ) which allows outbound traffic from a private subnet to reach the internet (or other AWS services), <em>but prevents the internet from initiating a connection with the subnet.</em></p><p>A <strong>NAT instance</strong> is an EC2 instance running a special AMI which does what the NAT gateway does but it’s not managed. Not recommended.</p><p><strong>Egress Only Internet Gateway</strong> is similar to the Internet Gateway but supports egress only and IPV6 only.</p><h4>Routing</h4><p>Each routing table must contain a route for the local CIDR block. The most specific route for an IP address is applied.</p><p>Border Gateway Protocol (<strong>BGP</strong>), propagates information about the network to allow for dynamic routing, used by Direct Connect and optionally by VPN. Each endpoint has an identifier called ASN (Autonomous System Number). Local routers have weights for outbound traffic, higher weight will be the preferred path.</p><h4>How to place your EC2 instances within a VPC</h4><p>Three type of placement groups of EC2 instances:</p><ul><li><strong>Clustered: </strong>Physically close, co-located in the same rack for lwer network latencies. You should allocate all the capacity beforehand, there might not be space in the rack to add capacity later. Single AZ only. If the rack goes down, so does the whole placement group.</li><li><strong>Spread: </strong>higher availability as they sit on different hardware, can also span multiple AZ (max 7 instances per group per AZ).</li><li><strong>Partition</strong>: hybrid solution, instances in the placement group are spread into partitions across racks.</li></ul><h4>Flowlogs</h4><p>Traffic logs in and out of a VPC. Some traffic is excluded (e.g. Amazon DNS, VPC Router, Amazon Time Sync Service, DHCP traffic, etc.)</p><h3>Network to VPC Connectivity</h3><h4>DYI VPN</h4><p>You can buy a VPN appliance or install aVPN software on an EC2 instance with access to the internet, this will give the max flexibility and control but unlike the the AWS managed VPN option you will come with updates, availability, etc. already sorted out.</p><h4>AWS VPN</h4><p>In order to define an AWS managed VPN you need to define three resources:</p><ul><li>a <strong>Customer Gateway</strong> (i.e. physical device or software which act as endpoint on the customer side of the VPN)</li><li>a <strong>Virtual Private Gateway</strong> (i.e. endpoint of the VPN in your AWS VPC)</li><li>a <strong>Site-To-Site VPN connection</strong> between the Customer Gateway and Virtual Private Gateway (uses the<strong> IPSec VPN protocols</strong> to manage auth and encryption of IP packets)</li></ul><p><strong>Bonus</strong>: you can use <strong>AWS VPN CloudHub</strong> to make your Virtual Private Gateway act as a hub to manage different customer gateways to communicate each other using an AWS VPN.</p><h4>Direct Connect</h4><p>Dedicated network over private lines straight into AWS backbone, not over the internet, from a “AWS Direct Connect Location” (e.g. third party data center). Provides more predictable network performances and potential cost reductions (data transfer <strong>to </strong>AWS is free — not <strong>from </strong>AWS though).</p><p>If you have particular security requirements you can use a VPN on top of a Direct Connection connection.</p><h3>VPC to VPC Connectivity</h3><h4>VPC Peering</h4><p>VPC Peering lets you connect two VPC networks together., possibly belonging to different AWS account. Transitive peering does not work, you need to explicitly define the links.</p><h4>AWS Transit</h4><p>Hub to manages traffic between different VPCs in a hub &amp; spoke model. n VPCs talking each other require (n-1)! VPC peerings (as transitive peering does not work), this is not scalable. With AWS Transit you define only one connection (to the Transit Gateway hub), making easier to scale the network.</p><h4>PrivateLink</h4><p>Private network between VPCs, AWS service or on promise servers. Prevents traffic from passing through the outside internet, can save money.</p><h4>VPC endpoint</h4><p>A<a href="https://docs.aws.amazon.com/vpc/latest/userguide/vpc-endpoints.html"> VPC endpoint</a> enables you to privately connect your VPC to supported AWS services and VPC endpoint services powered by AWS PrivateLink without requiring an internet gateway, NAT device, VPN connection, or AWS Direct Connect connection.</p><p><strong>Interface Endpoints </strong>are ENI with special DNS entries to redirect traffic and avoid it going out to the internet. You can secure them with Security Groups.</p><p><strong>Gateway Endpoints </strong>(fewer services supported e.g. S3, DDB) use prefix lists in the route table to redirect the traffic, again preventing it from going out in the internet. You can restrict access through custom policies (similar to IAM policies).</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c77f59ded19e" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Road to AWS Certification: Cache and Multi-tenant SaaS strategies]]></title>
            <link>https://medium.com/@alessiopiergiacomi/road-to-aws-certification-cache-and-multi-tenant-saas-strategies-aeffc85f9906?source=rss-ea1aff83a909------2</link>
            <guid isPermaLink="false">https://medium.com/p/aeffc85f9906</guid>
            <category><![CDATA[elasticache]]></category>
            <category><![CDATA[aws-certification]]></category>
            <category><![CDATA[aws]]></category>
            <dc:creator><![CDATA[Alessio Piergiacomi]]></dc:creator>
            <pubDate>Sat, 11 Apr 2020 11:07:28 GMT</pubDate>
            <atom:updated>2020-04-11T11:07:28.647Z</atom:updated>
            <content:encoded><![CDATA[<p>Two of the suggested readings for the AWS Certified Architect Professional exam are the <a href="https://d1.awsstatic.com/whitepapers/Multi_Tenant_SaaS_Storage_Strategies.pdf">SaaS Storage strategies</a> and the <a href="https://d0.awsstatic.com/whitepapers/performance-at-scale-with-amazon-elasticache.pdf">Performance at Scale with Amazon Elasticache</a> AWS Whitepapers. I’ve read them, and here’s my main takeaways.</p><h3>SaaS Storage strategies</h3><p>This whitepaper is all about three models to design the storage of a multi-tenant SaaS application on AWS, and how the models apply to RDS, DynamoDB and Redshift .</p><h4>Silo model</h4><p>Every tenant has its own completely independent database.</p><p><strong>Good for:<br>- </strong>Isolation<br>- Tenant level tuning<br>- Tenant level availability (smaller blast radius)<br>- Eventual compliance requirements</p><p><strong>Bad for:<br></strong>- increased costs<br>- increased complexity of pretty much every aspect (provisioning, deployments, maintenance)</p><h4>Bridge/Hybrid model</h4><p>One shared database instance/account, but each tenant has different “sub-databases” or schemas.</p><h4>Pool model</h4><p>Shared database, shared schema.</p><p><strong>Good for:<br></strong>- reduced costs <br>- easier to maintain, to deploy, to manage</p><p><strong>Bad for:<br></strong>- bigger blast radius<br>- requires good application level authorization policies (can’t rely on IAM, at least for some services)<br>- potential issues with uneven usage of resources between tenants (hot key problems*)<br>- scalability issues at some level (RDS databases have size limits)</p><p>*There is a nice suggestion using an additional DDB lookup table, keeping track of shards and their usage, and use it to “balance” out shards when deciding where to allocate a new key.</p><h3>Elasticache whitepaper</h3><p>I have found this whitepaper more interesting, these points stood out to me</p><h4>Memcached</h4><ul><li>Very simple but extremely scalable and fast, supporting multiple threads to take advantage of powerful multi-core machines (unlike Redis).</li><li>Complexity is built in the client, implementing a consistent hashing algorithm (i.e. key hashes are mapped to the closest integer representing a node, much more efficient in scaling than the simplistic hash % n servers algorithm, which requires old_n_server/new_n_server key re-mappings)</li></ul><h4>Redis</h4><ul><li>Fancier features than Memcached: lists, sets, sorted sets, pub/sub, persistency,</li><li>Less scalable than Memcached: runs mostly on a single thread and scales only vertically (you can scale horizontally by creating multiple clusters and sharding in the client, but you’ll lose the fancier features, and at that point you’re probably better off just using Memcached, unless if you specifically need persistence).</li><li>Can scale separately for reads (with replicas, also in different AZs) and writes (vertical scaling of the primary node, single AZ). Recommended deployments: multi-AZ with auto-failover.</li><li><em>Data loss might occur in replication if you have rapidly changing data (i.e. go for another database offering if it’s a critical requirement)</em></li><li>Examples of advanced Redis feature’s usage: leaderboard with sorted sets, chat messaging with ephemeral pub/sub, rapid queues</li><li>Redis supports backup/restore of snapshots from S3, backups are suggested with a minimum of 7 days retention</li></ul><h4>Caches in general</h4><ul><li>Beware of very frequently used cache keys, a lot of requests might hit the database at once when they cache items expire or get removed (thundering herd). Pre-warm caches if possible, use jitter on cache items TTL.</li><li>Monitor CPU usage (EngineCPUUtilization for Redis, which tracks the usage of the core used by the engine, other cores are under-utilized), cache misses, evictions (too high means I’m running out of space).</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=aeffc85f9906" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Road to AWS Certification: Storage services]]></title>
            <link>https://medium.com/@alessiopiergiacomi/road-to-aws-certification-storage-services-c203936cb2dc?source=rss-ea1aff83a909------2</link>
            <guid isPermaLink="false">https://medium.com/p/c203936cb2dc</guid>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[aws-certification]]></category>
            <dc:creator><![CDATA[Alessio Piergiacomi]]></dc:creator>
            <pubDate>Fri, 10 Apr 2020 11:24:49 GMT</pubDate>
            <atom:updated>2020-04-10T11:24:49.926Z</atom:updated>
            <content:encoded><![CDATA[<p>I did follow <a href="https://acloud.guru/">acloudguru’s</a> AWS Certified Architect Professional course structure and began my study from the storage services.</p><p>There are <strong>a lot </strong>of different storage services on AWS, sometimes overlapping in features (i.e. here is more than one “correct way” to do something using different AWS services).</p><p>There is a good <a href="https://d1.awsstatic.com/whitepapers/Storage/AWS%20Storage%20Services%20Whitepaper-v9.pdf">whitepaper</a> on all the storage options available <strong>in 2016</strong>: it’s comprehensive but unfortunately outdated. I recommend reading it for the trade-offs tables, but you definitely need to integrate it with some other source: I don’t have any good recommendation on this. I can only suggest to read the AWS official documentation if you spot a knowledge gap on a specific service.</p><p>I have extensively used in the past EBS and S3, so I wasn’t really interested in studying these (but admittedly I’m not super up-to-date with the latest updates to them products, so I’ll play around with them in the next few weeks). I spent most of my time trying to fit into my head the <strong>AWS Storage Gateway </strong>offering.</p><h4>AWS Storage Gateway</h4><p>I have never used it, but I can see how it’s valuable if you still have on-premise servers. It’s deployed as a virtual machine that you can install in your on-premise hardware (or in an EC2 instance) and offers some kind of storage virtualisations.</p><p>It comes in different flavours:</p><ul><li><strong>File gateway: </strong>store and retrieve files to S3 using a NFS (or SMB) mount in your on-premise servers. You know where files are mapped in S3 and you can access them individually from any other AWS service.</li><li><strong>Cached Volume for Volume Gateway</strong>: storage volume mountable as iSCSI device on-premise, but actually backed on the cloud (as EBS snapshot on S3, I believe). There is a local cache of the most frequently accessed files stored on-premise. Requires less local storage than the next option, but also provides optimal latency for the most frequently accessed files only.</li><li><strong>Stored Volume for Volume Gateway: </strong>storage volume mountable as iSCSI device on-premise, entirely stored locally on-premise but asynchronously backed on the cloud in the form of EBS snapshots to S3. Classic use case: offsite backup. Encryption happens in the Volume Gateway, so if you run it on-premise unencrypted data never leave the on-premise site.</li><li><strong>Tape gateway</strong>: virtual taped storage on the cloud, supposedly a drop-in replacement to on-premise tape archive, stored in AWS cheapest S3 class cold storages (Glacier or Deep Archive).</li></ul><p>My knowledge on the Gateway Storage is super-shallow, but I’ll look for gaps in my knowledge and fill them later, at the stage when I will be ready for full exam simulations.</p><h4>Trade-offs and evaluating solutions</h4><p>~60% of the exam will be on “<em>Designing new solution</em>” and “<em>Improving existing solutions</em>” according to the <a href="https://d1.awsstatic.com/training-and-certification/docs-sa-pro/AWS_Certified_Solutions_Architect_Professional-Exam_Guide_1.2.pdf">official Exam Guide</a>, so I would imagine the most impactful thing to study are the trade-offs and evaluation guidelines to pick a storage service given some requirement.</p><p><strong><em>Requires extreme performances and does not strictly require data persistency?</em></strong></p><p>EC2 Local Instance Store: it’s on the same physical machine as the EC2 instance where it is mounted (i.e. 0 network latency), see the appendix below for surprising performance comparison.</p><p>Data is not persisted if you stop an EC2 machine (even if you restart it later). If you only reboot the instance data doesn’t get lost.</p><p><strong><em>Do you need to share the data between different EC2 machines?</em></strong></p><p>Use EFS (you can mount an EFS volume on multiple EC2 instances) or S3.</p><p><strong><em>Do you want to pay per usage or per provisioned space?</em></strong></p><p>With EC2 instance store and EBS you pay per provisioned space. EFS, S3 and the Storage Gateway solution let you pay per usage.</p><p><strong><em>How much do you care high durability and availability?</em></strong></p><p>S3 boasts 11 nines durability, so it’s a clear winner on that aspect. EBS is the least “high available” of the lot, because<em> it’s only replicated within an AZ,</em> unlike EFS and S3 (which also has an One-Zone infrequent access option if you have specific cost requirements). EBS has a snapshot feature if you need to increase durability or have specific disaster recovery requirements. This is helpful for e.g. database file systems.</p><p><strong><em>Does your data change very frequently?</em></strong></p><p>EBS and EFS are better solution than S3 in this case, with the latter being eventually consistent and also offering higher latencies.</p><p><strong><em>Do you need to access your data rarely?</em></strong></p><p>The best option here is S3, picking an appropriate storage classes for your latency, availability and cost requirements. See Appendix 2 for all the storage classes currently available (I remember this being the subject on multiple questions on my Associate level certification, well worth a review).</p><p><strong><em>Do you need to serve static data or web content?</em></strong></p><p>The <a href="https://d1.awsstatic.com/whitepapers/Storage/AWS%20Storage%20Services%20Whitepaper-v9.pdf">whitepaper</a> suggests EFS or S3 in this case, but I would go with S3 here: setting a public static website with S3 it’s as easy as it gets. Providing access to static data it’s easy too, with granular permissions enforceable.</p><p>If you want improvements in performance IN and OUT from AWS data centers, you can use S3 Transfer Acceleration to make the clients communicate with the AWS edge location, which is usually closer to the client location (there are less than a couple dozens of AWS regions and hundreds of edge locations).</p><p>Similarly in concept, you can also use CloudFront which is also being served by the edge location data centers, but also caching the content in the process, so subsequent requests won’t just reach S3 faster, they’ll be entirely served by the CloudFront cache.</p><p><strong><em>Do you need to do some analytics on your stored data?</em></strong></p><p>S3 shines again here: AWS Athena and Redshift Spectrum let you run queries against your structured data stored on S3.</p><p>Athena was a bit immature when I played with it 3–4 years ago, but I’m sure it improved in the meantime. Redshift Spectrum proposition sounds interesting: keep the most frequently used data in your Redshift cluster, and the rest of the data on S3, combine them in your queries. I haven’t used it yet, but I can see how it makes sense as a proposition, considering I remember Redshift being very slow to scale up/down in my experience at Amazon.</p><p><strong><em>Do you need to make sure files can’t be deleted (e.g. for compliance reasons)?</em></strong></p><p>S3 is the right choice, you can define Vault Lock Policies for S3 Glacier which prevents any deletion, or add some multi factor authentication to the delete operation on S3 standard class buckets.</p><h4>Conclusion</h4><p>The “storage on AWS” subject is super broad and I feel like I haven’t even scratched the surface. I want to keep pushing with my study and get the certification as some kind of “result” out of this COVID quarantine period, so I’ll try to not get discouraged by this 😊.</p><h4>Appendix: Impressive IOPS capabilities by I/O optimized instances:</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/585/0*sIrPKhiLyrD_9Jn8" /><figcaption>I/O optimized instances local store performances</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/698/0*FOq8jWkn3vyi96Z6" /><figcaption>EBS IOPS pale in comparison to the previous table.</figcaption></figure><h4>Appendix 2 — S3 storage classes options:</h4><p>From the <a href="https://aws.amazon.com/s3/storage-classes/">official documentation</a>:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/901/1*po1FdwSjoFEuFtwVlzZZ4g.png" /></figure><p>Pricing for storage decreases going from left to right, while (mostly) API calls cost increases in the opposite direction (you’re supposed to do less frequent calls to Glacier or Infrequent Access Storage).</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c203936cb2dc" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Road to AWS Architect Professional Certification begins]]></title>
            <link>https://medium.com/@alessiopiergiacomi/road-to-aws-architect-professional-certification-begins-a8e542082a4a?source=rss-ea1aff83a909------2</link>
            <guid isPermaLink="false">https://medium.com/p/a8e542082a4a</guid>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[acloudguru]]></category>
            <category><![CDATA[aws-certification]]></category>
            <category><![CDATA[certification-courses]]></category>
            <dc:creator><![CDATA[Alessio Piergiacomi]]></dc:creator>
            <pubDate>Thu, 09 Apr 2020 10:07:44 GMT</pubDate>
            <atom:updated>2020-04-09T10:07:44.040Z</atom:updated>
            <content:encoded><![CDATA[<p>Since the COVID situation provided me with lots of free time, I have decided to spend some on reviewing my AWS certifications. I’ll write a series of blog post on the process, to keep myself accountable to pursue this objective.</p><p>I currently possess the <strong>AWS Certified Developer Associate</strong> and <strong>AWS Certified Architect Associate</strong> certifications expiring in July 2020, which should provide me of two 50% off voucher for new certification exams of my choice. I’m not going to try and renew both of them, I would like to try something different and go for the <strong>AWS Certified Architect Professional</strong> certification, which will also renew my old AWS Certified Architect Associate for 3 more years (so I should still be able to say I own 2 certifications 😬).</p><p><strong>The exam difficulty</strong></p><p>The exam is supposed to be harder than the ones I took three years ago, but how much? In order to understand how much study is required for this, I had a quick peek at the <a href="https://d1.awsstatic.com/Train%20%26%20Cert/docs/AWS_certified_solutions_architect_professional_examsample.pdf">sample questions</a> on the AWS website.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/729/0*ytw_cracwXztiTKI" /><figcaption>Example question</figcaption></figure><p>My first impression is “this looks really hard”! According to <a href="http://media.amazonwebservices.com/jp/certification/AWS_certified_solutions_architect_professional_examsample0701_08_final.pdf">this Japanese official file</a> the correct answer is D. I am not sure why this is not C, in a production system I wouldn’t store logs on an ephemeral disk and I thought that one of the many “S3 server-side encryption” options was able to satisfy the “logs only decrypted by employee of your company” requirement, but it looks like that’s not the case.</p><p>I’ll have to study quite a bit before approaching the exam. I think I was in a slightly better position 3 years ago, at my current company (<a href="https://monzo.com/blog/technology">Monzo</a>) we just deploy and operate open source software, such as Cassandra, Kafka, HashiCorp Vault, etc.) as opposed to use AWS out-of-the-box managed services as I did in my previous 2 roles, especially at Amazon Prime Video where paying an extra to AWS for managed services was unsurprisingly the recommended guideline.</p><p><strong>Where to study?<br></strong>For the past two AWS certification I remember buying <a href="https://acloud.guru/">acloud.guru</a> courses. The associates exams didn’t go super deep and the courses were good enough that covered most of the ground. I decided to trust them once again, heading to their website.</p><p>Apparently their business model changed, now they don’t charge you X$ to buy a course, but they since then moved to everyone’s favourite (ironic) monthly subscription model. <em>If your goal is a certification I’m not sure a yearly subscription makes any sense</em>: I’m going to go for a monthly subscription for a single month and then cancel it, but to begin with, I have started with the free weekly trial.</p><p><strong>A Cloud Guru Professional Architect Certification preparation course</strong></p><p>I’m not super-impressed when I see the amount of videos available for this course, it’s ~12.5 hours, pretty much the same as the corresponding Associate course which has to cover less topics.</p><p>I liked the introduction: the instructor is careful to not over-promise, pointing out the course is just a guideline but you’ll need to read AWS whitepapers, watch AWS re:Invent videos, and have expertise on the field in order to ace the exam.</p><p>They also introduce the <a href="https://cft.vanderbilt.edu/guides-sub-pages/blooms-taxonomy/">Bloom Taxonomy</a> concept to point out the different expectations between the Associate level and the Professional level certifications, which I found really a really interesting concept more broadly, not limited to the AWS Certifications world.</p><p>A short introduction to how the exam works, and a reminder (I’ve already noticed in the sample questions), that <em>exam questions are long, and have more than one answer technically correct, but only one also “contextually” correct according to all the specifics of the question</em>.</p><p>The course then proceeds to storages, but I guess that’s the topic for the next blog post..</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a8e542082a4a" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Pre-mortem as a new tool?]]></title>
            <link>https://medium.com/@alessiopiergiacomi/pre-mortem-as-a-new-tool-fabff9e4182c?source=rss-ea1aff83a909------2</link>
            <guid isPermaLink="false">https://medium.com/p/fabff9e4182c</guid>
            <category><![CDATA[postmortem]]></category>
            <category><![CDATA[technical-debt]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[project-management]]></category>
            <category><![CDATA[agile-development]]></category>
            <dc:creator><![CDATA[Alessio Piergiacomi]]></dc:creator>
            <pubDate>Fri, 29 Dec 2017 00:36:31 GMT</pubDate>
            <atom:updated>2017-12-29T00:51:01.996Z</atom:updated>
            <content:encoded><![CDATA[<p>In complex software systems incidents usually lead to <strong>post-mortem</strong> <strong>examinations</strong>, with detailed post-mortem documents reporting the findings. The name come from the medicine field, where the post-mortem examinations (commonly known as <strong>autopsy</strong>) had been carried out for centuries.</p><p>Reading post-mortem documents is highly educative (please read <a href="https://danluu.com/postmortem-lessons/">this tremendously good blog post about it</a>), in my experience<strong> because a recent post-mortem is up-to-date and very detailed by definition</strong>, two characteristics unfortunately rare to find in internal documentation.</p><p>I casually stumbled upon the concept of <strong>pre-mortem, </strong>developed by research psychologist Gary Klein and <a href="https://hbr.org/2007/09/performing-a-project-premortem">published on Harvard Business Review in 2007</a>.</p><p>This reminded me of Amazon’s approach of <em>working backwards</em> (<a href="http://www.allthingsdistributed.com/2006/11/working_backwards.html">explained here by AWS CTO Werner Wogel</a>), but with a different starting point: a spectacular failure rather than a great success. I wonder how these two approaches compare in terms of effectiveness.</p><p>And I wonder even more if pre-mortem as a tool can be used in our industry by development teams to help product owners and management to understand the depth and implications of technical debt.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=fabff9e4182c" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>