<?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:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Engineering Strategy: Technical]]></title><description><![CDATA[Technical posts on different technologies]]></description><link>https://learnings.aleixmorgadas.dev/s/technical</link><image><url>https://substackcdn.com/image/fetch/$s_!Jclx!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b983592-e8a9-4295-8dbb-61e4de81a493_1280x1280.png</url><title>Engineering Strategy: Technical</title><link>https://learnings.aleixmorgadas.dev/s/technical</link></image><generator>Substack</generator><lastBuildDate>Wed, 13 May 2026 12:40:25 GMT</lastBuildDate><atom:link href="https://learnings.aleixmorgadas.dev/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Aleix Morgadas]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[aleixmorgadas@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[aleixmorgadas@substack.com]]></itunes:email><itunes:name><![CDATA[Aleix Morgadas]]></itunes:name></itunes:owner><itunes:author><![CDATA[Aleix Morgadas]]></itunes:author><googleplay:owner><![CDATA[aleixmorgadas@substack.com]]></googleplay:owner><googleplay:email><![CDATA[aleixmorgadas@substack.com]]></googleplay:email><googleplay:author><![CDATA[Aleix Morgadas]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Stateful Testcontainers for Spring Boot 3.1 Dev Mode]]></title><description><![CDATA[Configuring containers to keep the state between executions to improve the DevEx. Using MongoDB as example.]]></description><link>https://learnings.aleixmorgadas.dev/p/stateful-testcontainers-for-spring</link><guid isPermaLink="false">https://learnings.aleixmorgadas.dev/p/stateful-testcontainers-for-spring</guid><dc:creator><![CDATA[Aleix Morgadas]]></dc:creator><pubDate>Wed, 06 Sep 2023 10:07:57 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!4KbB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F679e0d89-a5e9-4487-886e-29825bdd75e8_1002x698.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Spring Boot 3.1 introduced a lot of enhancements for DevEx. In particular, their integration with <a href="https://testcontainers.com/">Testcontainers</a> for test and DevMode.</p><h2><a href="https://docs.spring.io/spring-boot/docs/3.1.0/reference/html/features.html#features.testing.testcontainers.at-development-time">DevMode</a></h2><p>Now, you can declare your infrastructure dependencies and run your application in local machine by declaring via Spring Beans which Containers to use.</p><p>Something like:</p><pre><code>package dev.aleixmorgadas;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.devtools.restart.RestartScope;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.context.annotation.Bean;
import org.testcontainers.containers.BindMode;
import org.testcontainers.containers.MongoDBContainer;
import org.testcontainers.utility.DockerImageName;

import java.util.List;


@TestConfiguration(proxyBeanMethods = false)
public class TestMyApplication {

    public static void main(String[] args) {
        SpringApplication.from(MyApplication::main)
            .with(TestMyApplicationon.class).run(args);
    }

    @Bean
    @RestartScope
    @ServiceConnection
    MongoDBContainer mongoContainer() {
        return new MongoDBContainer(DockerImageName.parse("mongo:6.0.8"));
    }
}</code></pre><p>With this code, we are telling Spring to use a MongoContainer and replace the configuration with the Container one via `<code>@ServiceConnection</code>` annotation.</p><p>Shortly after using it you will find something frustrating.</p><div class="pullquote"><p>Your database state disappeared after stopping the application.</p></div><h2>The missing developer experience - Stateful containers</h2><p>Compared to tests that you want to start clean on each execution, when developing in local you aim to keep the state between runs.</p><p>Here we have two options:</p><ol><li><p>Testcontainers <a href="https://java.testcontainers.org/features/reuse/">reuse feature</a>. It tells Testcontainers to not stop the container, and when we start again, it will reuse the same container instance.</p></li><li><p>Add a volume.</p></li></ol><h3>1. Reuse container</h3><p>Let&#8217;s declare the <code>mongoContainer</code> as a reusable with a simple flag.</p><pre><code>@Bean
@RestartScope
@ServiceConnection
MongoDBContainer mongoContainer() {
    return new MongoDBContainer(DockerImageName.parse("mongo:6.0.8"))
           .withReuse(true);
}</code></pre><p><strong>Pro</strong></p><ul><li><p>The container will keep its state between executions.</p></li></ul><p><strong>Cons</strong></p><ul><li><p>If we restart our computer or just stop the container, we will lose the sate.</p></li></ul><h3>2. Adding a volume</h3><p><strong>MongoClient example</strong></p><pre><code><code>@Bean
@RestartScope
@ServiceConnection
MongoDBContainer mongoContainer() {
    return new MongoDBContainer(DockerImageName.parse("mongo:6.0.8")) {
            @Override
            public void configure() {
                withFileSystemBind("./.data", "/data/db");
                waitingFor(Wait.forLogMessage("(?i).*waiting for connections.*", 1));
            }

            @Override
            protected void containerIsStarted(InspectContainerResponse containerInfo, boolean reused) {
                // Disable default configuration due to replica set breaking configuration with stateful approach
            }
        };
}</code></code></pre><p><strong>Postgres example</strong></p><pre><code><code>@Bean
@RestartScope
@ServiceConnection
PostgreSQLContainer&lt;?&gt; postgresContainer() {
    return new PostgreSQLContainer&lt;&gt;(DockerImageName.parse("postgres:15"))
        .withFileSystemBind("./.data", "/var/lib/postgresql/data");
}</code></code></pre><p><strong>Pro</strong></p><ul><li><p>It keeps the state between executions and keeps the data after stopping the container.</p></li></ul><p><strong>Cons</strong></p><ul><li><p>You have state &#129335;&#8205;&#9794;&#65039;.</p></li></ul><div><hr></div><p>At this point, we fixed the problem with the state, but if we are developing in local, we might need to access the database to check anything.</p><h2>Accessing the database painlessly - Fixed <s>Random</s> Ports</h2><p>Testcontainers was originally intended for tests (and lucky us, we are seeing that it applies to more areas than just tests), it has some design decisions meant for testing best practices.</p><p>One of those best practices are <a href="https://java.testcontainers.org/features/networking/">random ports</a>. </p><blockquote><p><em>From the host's perspective</em> Testcontainers actually exposes this on a random free port. This is by design, to avoid port collisions that may arise with locally running software or in between parallel test runs.</p></blockquote><p>This is a great decision from a Testing point of view, and I fully recommend following this approach. BUT, when I&#8217;m developing in local, I don&#8217;t want to change my DB Tool each time the port changes.</p><p>We have two options:</p><ol><li><p>Fixed ports</p></li><li><p><a href="https://testcontainers.com/desktop/">Testcontainers Desktop</a></p></li></ol><h3>1. Fixed ports</h3><p>This is the fastest to apply, into your DevMode Configuration.</p><pre><code>@Bean
@RestartScope
@ServiceConnection
MongoDBContainer mongoContainer() {
    var container = new MongoDBContainer(DockerImageName.parse("mongo:6.0.8"));
    container.setPortBindings(List.of("55555:27017"));
    return container;
}</code></pre><p><strong>Pros</strong></p><ul><li><p>You don&#8217;t need to change your connection confirguration each time you start your application.</p></li></ul><p><strong>Cons</strong></p><ul><li><p>You might have port collitions.</p></li></ul><h3><a href="https://testcontainers.com/desktop/">2. Testcontainers Desktop</a></h3><p>Testcontainers is well aware of this problem and they provided a solution for it via the Testcontainers Desktop.</p><p>You can see the full feature description <a href="https://newsletter.testcontainers.com/announcements/set-fixed-ports-to-easily-debug-development-services">here</a>.</p><p>It added a new option called `Development Services` in the application.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4KbB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F679e0d89-a5e9-4487-886e-29825bdd75e8_1002x698.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4KbB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F679e0d89-a5e9-4487-886e-29825bdd75e8_1002x698.jpeg 424w, https://substackcdn.com/image/fetch/$s_!4KbB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F679e0d89-a5e9-4487-886e-29825bdd75e8_1002x698.jpeg 848w, https://substackcdn.com/image/fetch/$s_!4KbB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F679e0d89-a5e9-4487-886e-29825bdd75e8_1002x698.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!4KbB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F679e0d89-a5e9-4487-886e-29825bdd75e8_1002x698.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4KbB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F679e0d89-a5e9-4487-886e-29825bdd75e8_1002x698.jpeg" width="1002" height="698" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/679e0d89-a5e9-4487-886e-29825bdd75e8_1002x698.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:698,&quot;width&quot;:1002,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!4KbB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F679e0d89-a5e9-4487-886e-29825bdd75e8_1002x698.jpeg 424w, https://substackcdn.com/image/fetch/$s_!4KbB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F679e0d89-a5e9-4487-886e-29825bdd75e8_1002x698.jpeg 848w, https://substackcdn.com/image/fetch/$s_!4KbB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F679e0d89-a5e9-4487-886e-29825bdd75e8_1002x698.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!4KbB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F679e0d89-a5e9-4487-886e-29825bdd75e8_1002x698.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Which comes with a lot of preconfigured modules which what they do is map the random port to the prefeered port of the infrastructure you are running.</p><p>Here an Redis example of how it is configured for you as default config.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!MagK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6194b7f2-0b51-41a9-9aac-2fac92674ac9_2068x582.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!MagK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6194b7f2-0b51-41a9-9aac-2fac92674ac9_2068x582.png 424w, https://substackcdn.com/image/fetch/$s_!MagK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6194b7f2-0b51-41a9-9aac-2fac92674ac9_2068x582.png 848w, https://substackcdn.com/image/fetch/$s_!MagK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6194b7f2-0b51-41a9-9aac-2fac92674ac9_2068x582.png 1272w, https://substackcdn.com/image/fetch/$s_!MagK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6194b7f2-0b51-41a9-9aac-2fac92674ac9_2068x582.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!MagK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6194b7f2-0b51-41a9-9aac-2fac92674ac9_2068x582.png" width="1456" height="410" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6194b7f2-0b51-41a9-9aac-2fac92674ac9_2068x582.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:410,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!MagK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6194b7f2-0b51-41a9-9aac-2fac92674ac9_2068x582.png 424w, https://substackcdn.com/image/fetch/$s_!MagK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6194b7f2-0b51-41a9-9aac-2fac92674ac9_2068x582.png 848w, https://substackcdn.com/image/fetch/$s_!MagK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6194b7f2-0b51-41a9-9aac-2fac92674ac9_2068x582.png 1272w, https://substackcdn.com/image/fetch/$s_!MagK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6194b7f2-0b51-41a9-9aac-2fac92674ac9_2068x582.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Pros</strong></p><ul><li><p>You don&#8217;t need to change your connection confirguration each time you start your application.</p></li></ul><p><strong>Cons</strong></p><ul><li><p><s>You need to install Testcontainers Desktop</s>. None &#128516;</p></li></ul><p></p>]]></content:encoded></item><item><title><![CDATA[Configuring CDK with GitHub Actions and OIDC]]></title><description><![CDATA[OpenID Connect (OIDC) allows your GitHub Actions workflows to access resources in Amazon Web Services (AWS), without needing to store the AWS credentials as long-lived GitHub secrets.]]></description><link>https://learnings.aleixmorgadas.dev/p/configuring-cdk-with-github-actions</link><guid isPermaLink="false">https://learnings.aleixmorgadas.dev/p/configuring-cdk-with-github-actions</guid><dc:creator><![CDATA[Aleix Morgadas]]></dc:creator><pubDate>Sat, 29 Jul 2023 12:40:16 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!6GEy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7689af70-ec6b-4c1c-8aed-e179c8203448_1600x470.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>OpenID Connect (OIDC) allows your GitHub Actions workflows to access resources in Amazon Web Services (AWS), without needing to store the AWS credentials as long-lived GitHub secrets.</p><p><a href="https://aws.amazon.com/cdk/">AWS CDK</a> helps you define your cloud application resources using familiar languages such as python, node, and more.</p><p>If you setup from the beginning using this guideline, you will have secured your connection between GitHub Actions and AWS without needing to expose the AWS credentials as GitHub Secrets.</p><h2>Boostrap your infrastructure</h2><p>CDK provides a way to boostrap all the necessary resources to start deploying using CDK in your aws account.</p><p>The next command assumes you have configured in your local machine the aws credentials and region configuration. If not, please refer to the <a href="https://docs.aws.amazon.com/cdk/v2/guide/bootstrapping.html">official guideline</a> on how to specify those credentials.</p><pre><code><code>npx cdk bootstrap</code></code></pre><p>After some minutes, you will see in your IAM &gt; Roles a set of roles created by CDK to manage your infrastructure.</p><p>We will use them on the next steps to allow GitHub to deploy CloudFormation Stack changes assuming those roles.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6GEy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7689af70-ec6b-4c1c-8aed-e179c8203448_1600x470.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6GEy!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7689af70-ec6b-4c1c-8aed-e179c8203448_1600x470.png 424w, https://substackcdn.com/image/fetch/$s_!6GEy!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7689af70-ec6b-4c1c-8aed-e179c8203448_1600x470.png 848w, https://substackcdn.com/image/fetch/$s_!6GEy!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7689af70-ec6b-4c1c-8aed-e179c8203448_1600x470.png 1272w, https://substackcdn.com/image/fetch/$s_!6GEy!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7689af70-ec6b-4c1c-8aed-e179c8203448_1600x470.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6GEy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7689af70-ec6b-4c1c-8aed-e179c8203448_1600x470.png" width="1456" height="428" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7689af70-ec6b-4c1c-8aed-e179c8203448_1600x470.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:428,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:77123,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!6GEy!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7689af70-ec6b-4c1c-8aed-e179c8203448_1600x470.png 424w, https://substackcdn.com/image/fetch/$s_!6GEy!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7689af70-ec6b-4c1c-8aed-e179c8203448_1600x470.png 848w, https://substackcdn.com/image/fetch/$s_!6GEy!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7689af70-ec6b-4c1c-8aed-e179c8203448_1600x470.png 1272w, https://substackcdn.com/image/fetch/$s_!6GEy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7689af70-ec6b-4c1c-8aed-e179c8203448_1600x470.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2>Create a new role for github-actions to assume</h2><p>I found more convinient to create a dedicated role for GitHub Actions to assume with the necessary trust relationship and permissions.</p><p>Go to IAM &gt; Roles and Create Role. We will choose <code>Custom trust policy</code></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-BC_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9c312fa-5ca9-4dcf-946b-15157c76e39e_1920x968.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-BC_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9c312fa-5ca9-4dcf-946b-15157c76e39e_1920x968.png 424w, https://substackcdn.com/image/fetch/$s_!-BC_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9c312fa-5ca9-4dcf-946b-15157c76e39e_1920x968.png 848w, https://substackcdn.com/image/fetch/$s_!-BC_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9c312fa-5ca9-4dcf-946b-15157c76e39e_1920x968.png 1272w, https://substackcdn.com/image/fetch/$s_!-BC_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9c312fa-5ca9-4dcf-946b-15157c76e39e_1920x968.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-BC_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9c312fa-5ca9-4dcf-946b-15157c76e39e_1920x968.png" width="1456" height="734" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f9c312fa-5ca9-4dcf-946b-15157c76e39e_1920x968.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:734,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:169555,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!-BC_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9c312fa-5ca9-4dcf-946b-15157c76e39e_1920x968.png 424w, https://substackcdn.com/image/fetch/$s_!-BC_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9c312fa-5ca9-4dcf-946b-15157c76e39e_1920x968.png 848w, https://substackcdn.com/image/fetch/$s_!-BC_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9c312fa-5ca9-4dcf-946b-15157c76e39e_1920x968.png 1272w, https://substackcdn.com/image/fetch/$s_!-BC_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9c312fa-5ca9-4dcf-946b-15157c76e39e_1920x968.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3>Trust relationship</h3><p>We will copy the next code replacing the values of:</p><ul><li><p>&lt;account_id&gt; with your account id from AWS.</p></li><li><p>&lt;org&gt;/&lt;repo&gt; with the repositories that should be able to change AWS resources.</p></li></ul><pre><code>{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "RoleForGitHub",
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::&lt;account_id&gt;:oidc-provider/token.actions.githubusercontent.com"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
                    "token.actions.githubusercontent.com:sub": [
                        "repo:&lt;org&gt;/&lt;repo&gt;:ref:refs/heads/main",
                        "repo:&lt;org&gt;/&lt;repo&gt;:ref:refs/heads/main"
                    ]
                }
            }
        }
    ]
}</code></pre><h3>Policies</h3><p>Next, it will ask us for the policies to add. We will click to the <code>Create new policy</code> button, and we will use the <code>JSON</code> format.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-cbP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bb28bb0-bcf5-42fa-b73d-410b5438c64b_1920x968.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-cbP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bb28bb0-bcf5-42fa-b73d-410b5438c64b_1920x968.png 424w, https://substackcdn.com/image/fetch/$s_!-cbP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bb28bb0-bcf5-42fa-b73d-410b5438c64b_1920x968.png 848w, https://substackcdn.com/image/fetch/$s_!-cbP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bb28bb0-bcf5-42fa-b73d-410b5438c64b_1920x968.png 1272w, https://substackcdn.com/image/fetch/$s_!-cbP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bb28bb0-bcf5-42fa-b73d-410b5438c64b_1920x968.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-cbP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bb28bb0-bcf5-42fa-b73d-410b5438c64b_1920x968.png" width="1456" height="734" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6bb28bb0-bcf5-42fa-b73d-410b5438c64b_1920x968.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:734,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:154578,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!-cbP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bb28bb0-bcf5-42fa-b73d-410b5438c64b_1920x968.png 424w, https://substackcdn.com/image/fetch/$s_!-cbP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bb28bb0-bcf5-42fa-b73d-410b5438c64b_1920x968.png 848w, https://substackcdn.com/image/fetch/$s_!-cbP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bb28bb0-bcf5-42fa-b73d-410b5438c64b_1920x968.png 1272w, https://substackcdn.com/image/fetch/$s_!-cbP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bb28bb0-bcf5-42fa-b73d-410b5438c64b_1920x968.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>We will copy pase the next code replacing:</p><ul><li><p>&lt;account&gt; by your AWS account number</p></li><li><p>&lt;region&gt; with the region you plan to deploy your resources. The same that cdk created during the `<code>cdk boostrap</code>` step. Copy paste those arn resources.</p></li></ul><pre><code>{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "assumerolecdk",
            "Effect": "Allow",
            "Action": [
                "sts:AssumeRole",
                "iam:PassRole"
            ],
            "Resource": [
                "arn:aws:iam::&lt;account&gt;:role/cdk-hnb659fds-lookup-role-&lt;account&gt;-&lt;region&gt;",
                "arn:aws:iam::&lt;account&gt;:role/cdk-hnb659fds-deploy-role-&lt;account&gt;-&lt;region&gt;",
                "arn:aws:iam::&lt;account&gt;:role/cdk-hnb659fds-file-publishing-role-&lt;account&gt;-&lt;region&gt;",
                "arn:aws:iam::&lt;account&gt;:role/cdk-hnb659fds-image-publishing-role-&lt;account&gt;-&lt;region&gt;"
            ]
        }
    ]
}</code></pre><h2>Verify that your role looks like</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!kp3h!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0435a72b-a5cb-416e-9b84-c6019ab6e658_1600x896.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!kp3h!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0435a72b-a5cb-416e-9b84-c6019ab6e658_1600x896.png 424w, https://substackcdn.com/image/fetch/$s_!kp3h!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0435a72b-a5cb-416e-9b84-c6019ab6e658_1600x896.png 848w, https://substackcdn.com/image/fetch/$s_!kp3h!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0435a72b-a5cb-416e-9b84-c6019ab6e658_1600x896.png 1272w, https://substackcdn.com/image/fetch/$s_!kp3h!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0435a72b-a5cb-416e-9b84-c6019ab6e658_1600x896.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!kp3h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0435a72b-a5cb-416e-9b84-c6019ab6e658_1600x896.png" width="1456" height="815" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0435a72b-a5cb-416e-9b84-c6019ab6e658_1600x896.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:815,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:122275,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!kp3h!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0435a72b-a5cb-416e-9b84-c6019ab6e658_1600x896.png 424w, https://substackcdn.com/image/fetch/$s_!kp3h!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0435a72b-a5cb-416e-9b84-c6019ab6e658_1600x896.png 848w, https://substackcdn.com/image/fetch/$s_!kp3h!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0435a72b-a5cb-416e-9b84-c6019ab6e658_1600x896.png 1272w, https://substackcdn.com/image/fetch/$s_!kp3h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0435a72b-a5cb-416e-9b84-c6019ab6e658_1600x896.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!DOpX!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ece93ec-6fc9-487e-a616-1d3736ebbf65_1587x875.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!DOpX!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ece93ec-6fc9-487e-a616-1d3736ebbf65_1587x875.png 424w, https://substackcdn.com/image/fetch/$s_!DOpX!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ece93ec-6fc9-487e-a616-1d3736ebbf65_1587x875.png 848w, https://substackcdn.com/image/fetch/$s_!DOpX!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ece93ec-6fc9-487e-a616-1d3736ebbf65_1587x875.png 1272w, https://substackcdn.com/image/fetch/$s_!DOpX!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ece93ec-6fc9-487e-a616-1d3736ebbf65_1587x875.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!DOpX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ece93ec-6fc9-487e-a616-1d3736ebbf65_1587x875.png" width="1456" height="803" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7ece93ec-6fc9-487e-a616-1d3736ebbf65_1587x875.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:803,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:128409,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!DOpX!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ece93ec-6fc9-487e-a616-1d3736ebbf65_1587x875.png 424w, https://substackcdn.com/image/fetch/$s_!DOpX!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ece93ec-6fc9-487e-a616-1d3736ebbf65_1587x875.png 848w, https://substackcdn.com/image/fetch/$s_!DOpX!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ece93ec-6fc9-487e-a616-1d3736ebbf65_1587x875.png 1272w, https://substackcdn.com/image/fetch/$s_!DOpX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ece93ec-6fc9-487e-a616-1d3736ebbf65_1587x875.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2>GitHub Action</h2><p>Now, you can tell GitHub Action to deploy the resources assuming the new role replacing the &lt;account&gt; and &lt;region&gt; with your particular case.</p><p>The next code assumes you are using CDK with node, if you use CDK with python, you need to adapt the code to setup python.</p><pre><code>name: Deployment

on:
  push:
    branches: [ "main" ]
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
    steps:
    - uses: actions/checkout@v3
    - name: Set up node 18
      uses: actions/setup-node@v3
      with:
        node-version: 18
        cache: npm
    - name: npm install
      run: npm install
    - name: npm tests
      run: npm tests
    - name: Configure AWS Credentials
      uses: aws-actions/configure-aws-credentials@v2
      with:
        aws-region: &lt;your region&gt;
        role-to-assume: arn:aws:iam::&lt;account&gt;:role/github-role
        role-session-name: deployment-session
    - name: cdk synth
      run: npx --yes cdk synth
    - name: cdk deploy
      run: npx --yes cdk deploy --require-approval never
</code></pre>]]></content:encoded></item><item><title><![CDATA[Spring Data JPA with Materialized Views]]></title><description><![CDATA[What to do when the View doesn't contain an ID and you want to use @Entity for DB Mapping]]></description><link>https://learnings.aleixmorgadas.dev/p/spring-data-jpa-with-materialized</link><guid isPermaLink="false">https://learnings.aleixmorgadas.dev/p/spring-data-jpa-with-materialized</guid><dc:creator><![CDATA[Aleix Morgadas]]></dc:creator><pubDate>Sat, 18 Sep 2021 08:53:53 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!klL-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fa301037e-1a6a-4a08-b99d-f5220c3f7484_1356x606.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I tend to forget how to combine Spring Data JPA with Materialized Views &#129318; That&#8217;s why this post is for me, so I can check later how I did it in the past.</p><p>I&#8217;m using PostgreSQL for this example.</p><h1>Tables and Views</h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!klL-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fa301037e-1a6a-4a08-b99d-f5220c3f7484_1356x606.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!klL-!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fa301037e-1a6a-4a08-b99d-f5220c3f7484_1356x606.png 424w, https://substackcdn.com/image/fetch/$s_!klL-!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fa301037e-1a6a-4a08-b99d-f5220c3f7484_1356x606.png 848w, https://substackcdn.com/image/fetch/$s_!klL-!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fa301037e-1a6a-4a08-b99d-f5220c3f7484_1356x606.png 1272w, https://substackcdn.com/image/fetch/$s_!klL-!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fa301037e-1a6a-4a08-b99d-f5220c3f7484_1356x606.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!klL-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fa301037e-1a6a-4a08-b99d-f5220c3f7484_1356x606.png" width="1356" height="606" data-attrs="{&quot;src&quot;:&quot;https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/a301037e-1a6a-4a08-b99d-f5220c3f7484_1356x606.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:606,&quot;width&quot;:1356,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:86843,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!klL-!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fa301037e-1a6a-4a08-b99d-f5220c3f7484_1356x606.png 424w, https://substackcdn.com/image/fetch/$s_!klL-!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fa301037e-1a6a-4a08-b99d-f5220c3f7484_1356x606.png 848w, https://substackcdn.com/image/fetch/$s_!klL-!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fa301037e-1a6a-4a08-b99d-f5220c3f7484_1356x606.png 1272w, https://substackcdn.com/image/fetch/$s_!klL-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fa301037e-1a6a-4a08-b99d-f5220c3f7484_1356x606.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><a href="https://github.com/aleixmorgadas/poc-spring-reactive-timescale/tree/main/src/main/resources/db/migration">Schemas here</a></figcaption></figure></div><ul><li><p><strong>Transactions Table</strong>: It records the Transactions you receive with the Asset (&#8364;, $, &#8230;).</p></li><li><p><strong>Account Balance</strong>: It gives the sum of all the Transactions to give the Account Current Balance per Asset.</p></li></ul><h1>Materialized View Schema</h1><p>The <code>Account Balance Materialized View</code> looks like:</p><pre><code>CREATE MATERIALIZED VIEW IF NOT EXISTS account_balance
AS
SELECT
    name,
    account_id,
    asset,
    sum(value) as balance
FROM
    transactions
GROUP BY name, account_id, asset
WITH NO DATA;</code></pre><p>See <a href="https://github.com/aleixmorgadas/poc-spring-reactive-timescale/blob/main/src/main/resources/db/migration/V1__.sql#L14-L26">source code here</a></p><h1>Spring @Entity that consumes the View</h1><p>In order to consume this view via Spring Boot Data JPA, we need to declare as the ID of the <code>@Entity</code> the fields used in the <code>GROUP BY</code>.</p><pre><code>class AccountBalanceId(
    val accountId: UUID = UUID.randomUUID(),
    val name: String = "",
    val asset: String = "",
): Serializable

@Entity
@IdClass(AccountBalanceId::class)
@Immutable
class AccountBalance(
    @Id
    val accountId: UUID,
    @Id
    val name: String,
    @Id
    val asset: String,
    val balance: Double
)

interface AccountBalanceRepository: CrudRepository&lt;AccountBalance, AccountBalanceId&gt; {
    fun findByAccountId(accountId: UUID): List&lt;AccountBalance&gt;
}</code></pre><p>See <a href="http://thttps://github.com/aleixmorgadas/poc-spring-reactive-timescale/blob/main/src/main/resources/db/migration/V5__.sql">@Entity here</a> and <a href="http://thttps://github.com/aleixmorgadas/poc-spring-reactive-timescale/blob/main/src/main/resources/db/migration/V5__.sql">@Repository here</a>.</p><h1><a href="https://github.com/aleixmorgadas/poc-spring-reactive-timescale">Full Source Code</a></h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://github.com/aleixmorgadas/poc-spring-reactive-timescale" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!tq8U!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F6dc93edb-b871-4aa4-8ee5-073d5ddd88a8_480x469.gif 424w, https://substackcdn.com/image/fetch/$s_!tq8U!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F6dc93edb-b871-4aa4-8ee5-073d5ddd88a8_480x469.gif 848w, https://substackcdn.com/image/fetch/$s_!tq8U!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F6dc93edb-b871-4aa4-8ee5-073d5ddd88a8_480x469.gif 1272w, https://substackcdn.com/image/fetch/$s_!tq8U!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F6dc93edb-b871-4aa4-8ee5-073d5ddd88a8_480x469.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!tq8U!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F6dc93edb-b871-4aa4-8ee5-073d5ddd88a8_480x469.gif" width="480" height="469" data-attrs="{&quot;src&quot;:&quot;https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/6dc93edb-b871-4aa4-8ee5-073d5ddd88a8_480x469.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:469,&quot;width&quot;:480,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:39680,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:&quot;https://github.com/aleixmorgadas/poc-spring-reactive-timescale&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!tq8U!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F6dc93edb-b871-4aa4-8ee5-073d5ddd88a8_480x469.gif 424w, https://substackcdn.com/image/fetch/$s_!tq8U!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F6dc93edb-b871-4aa4-8ee5-073d5ddd88a8_480x469.gif 848w, https://substackcdn.com/image/fetch/$s_!tq8U!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F6dc93edb-b871-4aa4-8ee5-073d5ddd88a8_480x469.gif 1272w, https://substackcdn.com/image/fetch/$s_!tq8U!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F6dc93edb-b871-4aa4-8ee5-073d5ddd88a8_480x469.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Working solution here <a href="https://github.com/aleixmorgadas/poc-spring-reactive-timescale">https://github.com/aleixmorgadas/poc-spring-reactive-timescale</a></p><h1>Meme for you</h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7alr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F5979e998-56c8-4b3b-a15d-dff6c74d01b8_650x617.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7alr!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F5979e998-56c8-4b3b-a15d-dff6c74d01b8_650x617.jpeg 424w, https://substackcdn.com/image/fetch/$s_!7alr!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F5979e998-56c8-4b3b-a15d-dff6c74d01b8_650x617.jpeg 848w, https://substackcdn.com/image/fetch/$s_!7alr!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F5979e998-56c8-4b3b-a15d-dff6c74d01b8_650x617.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!7alr!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F5979e998-56c8-4b3b-a15d-dff6c74d01b8_650x617.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7alr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F5979e998-56c8-4b3b-a15d-dff6c74d01b8_650x617.jpeg" width="650" height="617" data-attrs="{&quot;src&quot;:&quot;https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/5979e998-56c8-4b3b-a15d-dff6c74d01b8_650x617.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:617,&quot;width&quot;:650,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!7alr!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F5979e998-56c8-4b3b-a15d-dff6c74d01b8_650x617.jpeg 424w, https://substackcdn.com/image/fetch/$s_!7alr!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F5979e998-56c8-4b3b-a15d-dff6c74d01b8_650x617.jpeg 848w, https://substackcdn.com/image/fetch/$s_!7alr!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F5979e998-56c8-4b3b-a15d-dff6c74d01b8_650x617.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!7alr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F5979e998-56c8-4b3b-a15d-dff6c74d01b8_650x617.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><a href="https://www.commitstrip.com/en/2015/11/02/thats-brutal/?">Source</a></figcaption></figure></div>]]></content:encoded></item><item><title><![CDATA[DynamoDB as EventStore ]]></title><description><![CDATA[I would like to share with you how I managed to deploy a solution to store Domain Events in DynamoDB in 2 days (and mostly because of AWS permission issues...&#128517;).]]></description><link>https://learnings.aleixmorgadas.dev/p/dynamodb-as-eventstore</link><guid isPermaLink="false">https://learnings.aleixmorgadas.dev/p/dynamodb-as-eventstore</guid><dc:creator><![CDATA[Aleix Morgadas]]></dc:creator><pubDate>Wed, 11 Aug 2021 08:54:35 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!i-vR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc437f55-0a53-4f41-bca2-96e5843fad8a_1000x420.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!i-vR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc437f55-0a53-4f41-bca2-96e5843fad8a_1000x420.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!i-vR!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc437f55-0a53-4f41-bca2-96e5843fad8a_1000x420.png 424w, https://substackcdn.com/image/fetch/$s_!i-vR!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc437f55-0a53-4f41-bca2-96e5843fad8a_1000x420.png 848w, https://substackcdn.com/image/fetch/$s_!i-vR!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc437f55-0a53-4f41-bca2-96e5843fad8a_1000x420.png 1272w, https://substackcdn.com/image/fetch/$s_!i-vR!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc437f55-0a53-4f41-bca2-96e5843fad8a_1000x420.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!i-vR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc437f55-0a53-4f41-bca2-96e5843fad8a_1000x420.png" width="1000" height="420" data-attrs="{&quot;src&quot;:&quot;https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/bc437f55-0a53-4f41-bca2-96e5843fad8a_1000x420.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:420,&quot;width&quot;:1000,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;practical-dev&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="practical-dev" title="practical-dev" srcset="https://substackcdn.com/image/fetch/$s_!i-vR!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc437f55-0a53-4f41-bca2-96e5843fad8a_1000x420.png 424w, https://substackcdn.com/image/fetch/$s_!i-vR!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc437f55-0a53-4f41-bca2-96e5843fad8a_1000x420.png 848w, https://substackcdn.com/image/fetch/$s_!i-vR!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc437f55-0a53-4f41-bca2-96e5843fad8a_1000x420.png 1272w, https://substackcdn.com/image/fetch/$s_!i-vR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc437f55-0a53-4f41-bca2-96e5843fad8a_1000x420.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>I would like to share with you how I managed to deploy a solution to store Domain Events in DynamoDB in 2 days (and mostly because of AWS  permission issues...&#128517;).</p><p>I wanted a solution to store how the user interacted with different Domain  Models and decouple that storage from the monolithic so they can grow independently. I aimed to create something super simple, or at least not that complex, in 2 to 3 days.</p><p>I wanted to process events as:</p><p><code>Monolith sends message to &#10145;&#65039; SQS &#10145;&#65039; Triggers Lambda to store it into &#10145;&#65039; DynamoDB Table</code></p><p>Even though DynamoDB might not be an optimal solution to be used as Event Store, I have given it a try for the next reasons:</p><ul><li><p>It is fully managed by AWS</p></li><li><p>It is cheap enough</p></li><li><p>We don't require high write throughput nor read for the moment.</p></li><li><p>Able to encrypt the content</p></li></ul><h2>Implementation </h2><p>I decided to go with:</p><ul><li><p><a href="https://www.terraform.io/">Terraform</a> as Infrastructure as Code</p></li><li><p>Python for <a href="https://aws.amazon.com/lambda/">AWS Lambda</a></p></li></ul><p>You can find the <a href="https://github.com/aleixmorgadas/dynamodb-as-eventstore">source code here</a> &#128522;</p><p>Ready to be deployed into your cloud solution &#128170;&#128513;</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://github.com/aleixmorgadas/dynamodb-as-eventstore" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!inyN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F0fa73e16-8c98-41fc-aa7f-1f88dedb8a71_480x469.gif 424w, https://substackcdn.com/image/fetch/$s_!inyN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F0fa73e16-8c98-41fc-aa7f-1f88dedb8a71_480x469.gif 848w, https://substackcdn.com/image/fetch/$s_!inyN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F0fa73e16-8c98-41fc-aa7f-1f88dedb8a71_480x469.gif 1272w, https://substackcdn.com/image/fetch/$s_!inyN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F0fa73e16-8c98-41fc-aa7f-1f88dedb8a71_480x469.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!inyN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F0fa73e16-8c98-41fc-aa7f-1f88dedb8a71_480x469.gif" width="480" height="469" data-attrs="{&quot;src&quot;:&quot;https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/0fa73e16-8c98-41fc-aa7f-1f88dedb8a71_480x469.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:469,&quot;width&quot;:480,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:39680,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:&quot;https://github.com/aleixmorgadas/dynamodb-as-eventstore&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!inyN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F0fa73e16-8c98-41fc-aa7f-1f88dedb8a71_480x469.gif 424w, https://substackcdn.com/image/fetch/$s_!inyN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F0fa73e16-8c98-41fc-aa7f-1f88dedb8a71_480x469.gif 848w, https://substackcdn.com/image/fetch/$s_!inyN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F0fa73e16-8c98-41fc-aa7f-1f88dedb8a71_480x469.gif 1272w, https://substackcdn.com/image/fetch/$s_!inyN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F0fa73e16-8c98-41fc-aa7f-1f88dedb8a71_480x469.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div>]]></content:encoded></item></channel></rss>