<?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"><channel><title><![CDATA[Heapstack | Romaric Philogene's blog]]></title><description><![CDATA[I am CEO and co-founder of [Qovery](https://www.qovery.com) - I like to share my tech and entrepreneurial experience 👨‍💻 - contact me on [Twitter](https://twi]]></description><link>https://www.heapstack.sh</link><generator>RSS for Node</generator><lastBuildDate>Wed, 13 May 2026 21:27:28 GMT</lastBuildDate><atom:link href="https://www.heapstack.sh/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Kubernetes for Developers with Qovery]]></title><description><![CDATA[In the last 8 years, Kubernetes has emerged as the standard for orchestrating containerized applications. However, its complexity can be a barrier for many developers.

Disclaimer: I'm a co-founder of Qovery - but I guarantee that it's not a trap! Gi...]]></description><link>https://www.heapstack.sh/kubernetes-for-developers-with-qovery</link><guid isPermaLink="true">https://www.heapstack.sh/kubernetes-for-developers-with-qovery</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[Devops]]></category><category><![CDATA[developer experience]]></category><category><![CDATA[Developer]]></category><category><![CDATA[qovery]]></category><dc:creator><![CDATA[Romaric Philogène]]></dc:creator><pubDate>Sat, 13 Jan 2024 15:47:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1705161050021/5ccc2be7-1b05-4226-9f7a-2b66eaae6a67.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the last 8 years, Kubernetes has emerged as the standard for orchestrating containerized applications. However, its complexity can be a barrier for many developers.</p>
<blockquote>
<p>Disclaimer: I'm a co-founder of Qovery - but I guarantee that it's not a trap! Give it a try to Qovery if you are looking to get a very nice developer experience on top of your Kubernetes cluster.</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705161062856/1d4712e1-3113-4720-9a67-e860abb63f7d.jpeg" alt class="image--center mx-auto" /></p>
<p>Enter <a target="_blank" href="https://www.qovery.com">Qovery</a> - an Internal Developer Platform that can be installed on any Kubernetes cluster to bring a delightful and simplified developer experience. But don't take my word for granted. In this quick step-by-step article, I will show you how to deploy one of my <a target="_blank" href="https://github.com/evoxmusic/ShortMe-URL-Shortener">GitHub apps</a> and a Postgres database on my Kubernetes cluster running on GCP. And what's really really cool is that I don't even need to understand how Kubernetes work!</p>
<h2 id="heading-qovery-a-brief-overview">Qovery: A Brief Overview</h2>
<ul>
<li><p><strong>What is Qovery?</strong> An Internal Developer Platform that abstracts Kubernetes complexities, empowering developers to focus on their code.</p>
</li>
<li><p><strong>Key Benefits:</strong></p>
<ul>
<li><p>Fast and easy installation on any Kubernetes cluster.</p>
</li>
<li><p>Intuitive open-source interfaces (<a target="_blank" href="https://github.com/Qovery/console">Web</a>, <a target="_blank" href="https://github.com/Qovery/qovery-cli">CLI</a>, <a target="_blank" href="https://api-doc.qovery.com/">API</a>, <a target="_blank" href="https://registry.terraform.io/providers/Qovery/qovery/latest/docs">Terraform Provider</a>) for efficient app deployment and management.</p>
</li>
<li><p>No Kubernetes expertise is required for developers.</p>
</li>
<li><p>Highly customizable for Platform Engineers.</p>
</li>
<li><p>No YAML to write for Developers ;)</p>
</li>
<li><p>Generous free plan (no credit card required).</p>
</li>
</ul>
</li>
<li><p><strong>Who Uses Qovery?</strong> Over 60,000 developers and Platform Engineers, valuing its simplicity and efficiency.</p>
</li>
</ul>
<h2 id="heading-deploying-an-application-on-kubernetes-with-qovery">Deploying an Application on Kubernetes with Qovery</h2>
<h3 id="heading-step-1-set-up-your-qovery-account">Step 1: Set Up Your Qovery Account</h3>
<p>Connect to <a target="_blank" href="https://console.qovery.com">console.qovery.com</a> and sign in with GitHub, GitLab, or Bitbucket.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705149054671/028780f9-d2c6-4502-ad01-9b0a5b54f049.png" alt class="image--center mx-auto" /></p>
<p>Then, give a name to your <a target="_blank" href="https://hub.qovery.com/docs/using-qovery/configuration/organization/">Organization</a> and Choose the <code>Free</code> plan.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705149180129/4e24c0c6-7823-43de-bec6-050e594509c0.png" alt class="image--center mx-auto" /></p>
<p>Once your organization is created, you should get this view:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705149336753/98b6fa2e-f0ef-409b-8233-7165cf60de78.png" alt class="image--center mx-auto" /></p>
<blockquote>
<p>I recommend familiarizing yourself with <a target="_blank" href="https://hub.qovery.com/docs/getting-started/basic-concepts/">the basic concepts of Qovery</a> to understand what an organization, cluster, project, or environment is.</p>
</blockquote>
<h3 id="heading-step-2-connect-your-github-repository">Step 2: Connect Your GitHub Repository</h3>
<p>You can skip this part if you signed up with your GitHub account. Otherwise, you can connect your GitHub account and permit Qovery to get access to your public and/or private repositories.</p>
<p>Go to your <code>Organization settings</code> &gt; <code>Git repositories access</code> &gt; then, pick the option you want to connect your GitHub account.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705149695771/2281d2c5-1b17-4d78-b9e8-19fce5914180.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-step-3-install-qovery-on-your-kubernetes-cluster">Step 3: Install Qovery on Your Kubernetes Cluster</h3>
<p>To install Qovery on your Kubernetes cluster, you need to add a cluster into the Qovery interface:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705153251491/5529dfbb-f5fd-406e-8b3a-94e2b3ae0253.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705153326898/16a71fd9-daf2-486d-a19c-921626d7b0f5.png" alt class="image--center mx-auto" /></p>
<p>Add your Kubeconfig:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1705153373170/1385d1bc-6a6b-49d8-be1c-e9d6ac58ee4e.png" alt class="image--center mx-auto" /></p>
<p>Qovery will give you the commands and the generated helm configuration files you can download.</p>
<p>Then, you need to run the following on your Kubernetes cluster:</p>
<pre><code class="lang-bash">helm repo add qovery https://helm.qovery.com
helm repo update

helm upgrade --install -n qovery -f values-zXXX.yaml qovery
</code></pre>
<p>Congrats! 🥳 Your cluster is connected to Qovery. You can now deploy your apps.</p>
<h3 id="heading-step-4-deploy-your-application">Step 4: Deploy Your Application</h3>
<p>Now, we can deploy our GitHub app on our Kubernetes cluster. Check out this short video and look how fast it is.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.loom.com/share/6d86b6aaea014b5aa673c1ed2d90d355">https://www.loom.com/share/6d86b6aaea014b5aa673c1ed2d90d355</a></div>
<p> </p>
<p>Here is what I did:</p>
<ol>
<li><p>I created an Environment and then I created an Application.</p>
</li>
<li><p>I select my app from my GitHub repository</p>
</li>
<li><p>By default Qovery picks the <code>Dockerfile</code> at the root of my project but I can change it.</p>
</li>
<li><p>I set the CPU to <code>250m</code> and the RAM to <code>256 MB</code></p>
</li>
<li><p>I declared my app port to be <code>5555</code> and I tick the <code>expose publicly</code> option -&gt; So my app can be accessible from outside.</p>
</li>
<li><p>I deployed my app and it's accessible publicly (end of video)</p>
</li>
</ol>
<p>This is pretty cool right? It's not over! 😎</p>
<h3 id="heading-step-5-manage-and-monitor-your-application">Step 5: Manage and Monitor Your Application</h3>
<p>Qovery provides everything you need to manage (start, stop, restart, redeploy, delete) and check out your applications logs - directly streamed from your Kubernetes cluster. Yes!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.loom.com/share/871912e2051848dcbeb0f186e4ac5761">https://www.loom.com/share/871912e2051848dcbeb0f186e4ac5761</a></div>
<p> </p>
<p>Do you want to use Datadog or any third-party solutions? No problem... Everything compatible with Kubernetes is compatible with Qovery.</p>
<h3 id="heading-step-6-leverage-advanced-qovery-features">Step 6: Leverage Advanced Qovery Features</h3>
<p>I'm pretty sure you ask yourself, ok, that's great. But what about configuring your environment variables, your custom domain, or even deploy a database... Well, it's all covered :)</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.loom.com/share/ac5b4c354c134a2db618995d1c8c758a">https://www.loom.com/share/ac5b4c354c134a2db618995d1c8c758a</a></div>
<p> </p>
<p>Imagine, you can even securely connect to your database with the Qovery CLI 😎</p>
<pre><code class="lang-bash">~ $ qovery auth
pening your browser, waiting <span class="hljs-keyword">for</span> your authentication...
Info: Success

~ $ qovery port-forward -p 5556:5555
Info: Current context:
Organization | MyOrg
Project      | URL Shortener
Environment  | prod
Service      | DB
Type         | database


Info: Continue with port-forward <span class="hljs-built_in">command</span> using this context ?
Please <span class="hljs-built_in">type</span> <span class="hljs-string">"yes"</span> to validate context: yes

Listening on 127.0.0.1:5432 =&gt; 5432

~ $ psql <span class="hljs-variable">$DATABASE_URL</span>

psql &gt;
</code></pre>
<h2 id="heading-powerful-out-of-the-box-features">Powerful out-of-the-box features</h2>
<p>Here are a list of cool features you get out of the box:</p>
<ul>
<li><p><strong>Auto-deploy</strong>: if I do commit and push a change on my GitHub app - it will be automatically redeployed without any downtime</p>
</li>
<li><p><strong>Clone</strong>: this is my favorite feature! You can clone your app (or your complete environment) in one click. So, testing a new feature without impacting the original app is easily possible.</p>
</li>
<li><p><strong>Ephemeral Environment</strong>: For each Pull Request that I open for my app, Qovery will spin up a new environment</p>
</li>
<li><p>RBAC, GitHub Actions (CI/CD) integration, Logs, Deployment pipeline, env var interpolation, env var as a file, helm deployment, multiple clusters...</p>
</li>
</ul>
<p>There are so many cool features that I could write 10 other posts to talk about them exclusively. It's probably something that I'll do if you are interested to learn more about some of them :)</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Qovery demystifies Kubernetes for developers, making it accessible and manageable without requiring deep expertise. Feel free to <a target="_blank" href="https://www.qovery.com">try it now</a> on your Kubernetes cluster - it's free and will always be!</p>
<blockquote>
<p><a target="_blank" href="https://github.com/Qovery/console">If you like the Qovery web interface - give a star ⭐ - it's open source and coded in React ✨</a></p>
</blockquote>
<p><strong>Additional Resources:</strong></p>
<ul>
<li><p><a target="_blank" href="https://hub.qovery.com">Qovery Documentation</a></p>
</li>
<li><p><a target="_blank" href="https://discuss.qovery.com">Community Support and Discussions</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Internal Developer Platform vs Internal Developer Portal: What's The Difference?]]></title><description><![CDATA[In the evolving landscape of software development, two terms frequently emerge: "Internal Developer Platform" (IDP) and "Internal Developer Portal". These terms are often used interchangeably, leading to confusion. In this article, we aim to differen...]]></description><link>https://www.heapstack.sh/internal-developer-platform-vs-internal-developer-portal-whats-the-difference</link><guid isPermaLink="true">https://www.heapstack.sh/internal-developer-platform-vs-internal-developer-portal-whats-the-difference</guid><category><![CDATA[Devops]]></category><category><![CDATA[Platform Engineering ]]></category><category><![CDATA[developer experience]]></category><dc:creator><![CDATA[Romaric Philogène]]></dc:creator><pubDate>Sat, 16 Sep 2023 08:01:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1694851187954/2a0a8454-d4f9-4397-b085-2d24777870a5.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the evolving landscape of software development, two terms frequently emerge: "Internal Developer Platform" (IDP) and "Internal Developer Portal". These terms are often used interchangeably, leading to confusion. In this article, we aim to differentiate the two and highlight their importance in modern software engineering.</p>
<h2 id="heading-what-is-an-internal-developer-platform-idp">What is an Internal Developer Platform (IDP)?</h2>
<p>An IDP serves as the backbone of an engineering team, offering a toolkit for building, testing, and deploying applications. It aims to minimize complexities and accelerate the Software Development Life Cycle (SDLC).</p>
<h3 id="heading-characteristics-of-an-internal-developer-platform">Characteristics of an Internal Developer Platform:</h3>
<ul>
<li><p><strong>Self-Service Capabilities</strong>: Provides reusable tools and automated infrastructure operations.</p>
</li>
<li><p><strong>Developer Self-Service</strong>: Enables developers to independently access cloud environments and perform Day 2 operations.</p>
</li>
<li><p><strong>Transparency</strong>: Offers visibility into the underlying infrastructure, like CPU usage, dependencies, or Kubernetes setups.</p>
</li>
<li><p><strong>Flexibility</strong>: Adapts to changes, being loosely coupled from the underlying infrastructure.</p>
</li>
</ul>
<p><strong>Examples</strong>:</p>
<ul>
<li><p><a target="_blank" href="https://www.qovery.com/"><strong>Qovery</strong></a>: An IDP that cuts noise for developers by offering paved paths to production, testing, <a target="_blank" href="https://www.qovery.com/solutions/ephemeral-environments">ephemeral environments</a>, and actionable insights to improve software.</p>
</li>
<li><p><a target="_blank" href="https://www.withcoherence.com/"><strong>Coherence</strong></a>: Specializes in unifying disparate systems into a single platform.</p>
</li>
<li><p><a target="_blank" href="https://www.appvia.io"><strong>Appvia</strong></a>: Focuses on automating cloud-native technologies.</p>
</li>
</ul>
<h2 id="heading-what-is-an-internal-developer-portal">What is an Internal Developer Portal?</h2>
<p>An Internal Developer Portal serves as the user interface or the 'front-end' of the IDP. It allows developers to interact with the toolkit that the IDP provides.</p>
<h3 id="heading-characteristics-of-an-internal-developer-portal">Characteristics of an Internal Developer Portal:</h3>
<ul>
<li><p><strong>User Experience</strong>: Delivers a product-like experience for accessing resources.</p>
</li>
<li><p><strong>Software Catalog</strong>: Functions as a metadata store, offering essential data to operational staff.</p>
</li>
<li><p><strong>Workflow Automation</strong>: Enables operations to run workflows against the software catalog.</p>
</li>
<li><p><strong>API-First Approach</strong>: Evolves into a platform API, interacting with various components of the IDP.</p>
</li>
</ul>
<p><strong>Examples</strong>:</p>
<ul>
<li><p><a target="_blank" href="https://backstage.io/"><strong>Backstage</strong></a>: An open-source portal centralizing infrastructure tooling, services, and documentation.</p>
</li>
<li><p><a target="_blank" href="https://www.getport.io/"><strong>Port</strong></a>: Offers a no-code approach to creating customized developer experiences.</p>
</li>
<li><p><a target="_blank" href="https://www.cortex.io/"><strong>Cortex</strong></a>: Provides data-driven insights to support better engineering decisions.</p>
</li>
</ul>
<h2 id="heading-relationship-between-idp-and-developer-portal">Relationship Between IDP and Developer Portal</h2>
<p>The Internal Developer Portal serves as the "face" of the Internal Developer Platform. It allows developers to perform self-service operations and offers visibility into the infrastructure. The portal often evolves into a platform API, offering a unified interface for various interactions.</p>
<h2 id="heading-why-both-are-essential">Why Both Are Essential</h2>
<p>An Internal Developer Portal complements and enhances the Internal Developer Platform. While the Internal Developer Platform serves as the backend engine, the portal offers the user experience. Together, they optimize productivity, maintain quality standards, and streamline operations.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>While an Internal Developer Platform like <a target="_blank" href="https://www.qovery.com">Qovery</a> acts as the backbone, offering paved paths to production and actionable insights, the Internal Developer Portal serves as its front-end, facilitating interaction and visibility. Investing in both can significantly benefit organizations by maximizing developer productivity and operational efficiency.</p>
]]></content:encoded></item><item><title><![CDATA[Understanding the Basics of Application Autoscaling]]></title><description><![CDATA[Application autoscaling is a considerable subject. At first, it looks simple because everyone understands the goal and how conceptually it works, but it’s not that simple in practice.
Let’s start with a simple schema explaining what type of app auto-...]]></description><link>https://www.heapstack.sh/understanding-the-basics-of-application-autoscaling-1</link><guid isPermaLink="true">https://www.heapstack.sh/understanding-the-basics-of-application-autoscaling-1</guid><category><![CDATA[Devops]]></category><category><![CDATA[Kubernetes]]></category><category><![CDATA[Developer]]></category><dc:creator><![CDATA[Romaric Philogène]]></dc:creator><pubDate>Sat, 05 Aug 2023 06:52:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/pr5lUMgocTs/upload/db39dfce32ff7d8b61b59575e060d2da.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Application autoscaling is a considerable subject. At first, it looks simple because everyone understands the goal and how conceptually it works, but it’s not that simple in practice.</p>
<p>Let’s start with a simple schema explaining what type of app auto-scaling exists today:</p>
<p><img src="https://miro.medium.com/v2/resize:fit:972/0*7va74AJ1pLjea_ce" alt="Horizontal Autoscaling vs. Vertical Autoscaling vs. Multi-dimensional Autoscaling" class="image--center mx-auto" /></p>
<p>At <a target="_blank" href="https://www.qovery.com">Qovery</a>, we’re using horizontal and vertical autoscaling on a daily basis for our production at different levels, and the result is excellent when the tuning is made after days/weeks of statistics, analysis, and configuration.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:1400/0*ry6EfAzn6e8E2jIf" alt="Graph of Qovery Engine autoscaling triggered" class="image--center mx-auto" /></p>
<h1 id="heading-horizontal-autoscaling">Horizontal autoscaling</h1>
<p><img src="https://miro.medium.com/v2/resize:fit:912/0*z7L3A7REGC6CUl7D" alt="Horizontal Autoscaling" class="image--center mx-auto" /></p>
<p>Horizontal autoscaling is scaling up an application by adding more app instances to distribute the workload across all instances, allowing for increased capacity and improved performance.</p>
<blockquote>
<p>Application autoscaling is different than cluster autoscaling, but it’s somehow related. In the context where your app runs on a cluster (E.g., Kubernetes), the more your app scales up the number of instances, the more your app is likely to consume cluster resources, and the more the cluster is likely to scale up nodes.</p>
</blockquote>
<p>Horizontal scaling refers to automatically adding or removing instances based on predefined rules or metrics. When the workload increases, additional instances are dynamically provisioned to handle the increased demand. Conversely, excess instances are automatically terminated when the workload decreases to optimize resource utilization and cost.</p>
<p>Horizontal autoscaling offers several benefits, including:</p>
<ul>
<li><p><strong>Improved performance</strong>: By distributing the workload across multiple instances, horizontal scaling can handle increased traffic or resource-intensive tasks more effectively, reducing response times and improving overall performance.</p>
</li>
<li><p><strong>Enhanced availability</strong>: Additional instances provide redundancy and fault tolerance. If one instance fails or becomes overloaded, the load can be automatically distributed to other instances, ensuring uninterrupted service availability.</p>
</li>
<li><p><strong>Scalability</strong>: Horizontal scaling allows for seamless expansion of an application or system by adding more instances. This flexibility enables businesses to accommodate sudden surges in traffic or increased demand without impacting performance.</p>
</li>
<li><p><strong>Cost optimization</strong>: Autoscaling allows you to allocate resources based on actual demand. Scaling up or down based on workload ensures efficient resource utilization, preventing overprovisioning and reducing unnecessary costs.</p>
</li>
</ul>
<h1 id="heading-vertical-autoscaling">Vertical autoscaling</h1>
<p><img src="https://miro.medium.com/v2/resize:fit:876/0*7zAYHGrdB16bpgiG" alt="Vertical Autoscaling" class="image--center mx-auto" /></p>
<p>Vertical autoscaling is a way to make your application more resource-autonomous by upgrading the resources of a single application instead of adding more machines (and scaling horizontally). It’s like boosting your computer by increasing its CPU power, memory, storage, or network capacity.</p>
<p>With vertical autoscaling, you can improve your application’s performance without the need to manage many instances. It simplifies administration and reduces the complexity of handling a distributed system.</p>
<p>However, there’s a maximum limit to how much you can upgrade an instance before hitting hardware constraints. Also, scaling up or down vertically may require restarting or reconfiguring the machine, resulting in temporary downtime or disruption.</p>
<p>Vertical autoscaling is commonly used in traditional setups or when the workload can’t be easily distributed across multiple instances. It’s handy for applications that require a lot of computational power, memory, or specialized hardware configurations.</p>
<p>Although horizontal autoscaling has gained popularity with cloud computing and containers, vertical autoscaling still plays a role in optimizing the performance and resource utilization of individual instances in specific situations.</p>
<h1 id="heading-multidimensional-autoscaling-google-proprietary">Multidimensional autoscaling (Google proprietary)</h1>
<p><img src="https://miro.medium.com/v2/resize:fit:954/0*8z2Jzo4J5yROVoXj" alt="Multi-dimensional Autoscaling" class="image--center mx-auto" /></p>
<p>Multidimensional autoscaling is like having a super-smart system that automatically adjusts the resources of your application or system in multiple dimensions to handle changing demands. It’s all about ensuring your application has the right power and capacity when needed.</p>
<p>Think of it as a dynamic team of helpers that can scale up or down in terms of the number of instances and by upgrading or downgrading the resources within each instance. It’s like giving your application a turbo boost or dialing it down when the workload changes.</p>
<p>With multidimensional autoscaling, you don’t have to adjust resources or add more instances manually. The system takes care of it for you, continuously monitoring metrics like CPU usage, memory, network traffic, or any other custom-defined criteria.</p>
<p>When your application is experiencing high traffic or increased resource demands, multidimensional autoscaling will intelligently add more resources to ensure smooth performance and prevent any slowdowns or crashes. On the other hand, when the workload decreases, it will automatically scale down to optimize resource usage and save costs.</p>
<p>The beauty of multidimensional autoscaling is that it considers multiple factors to make the right decisions. It’s like having a super-smart teammate who knows when to boost your application and when to hold back to avoid wasting resources.</p>
<p>By employing multidimensional autoscaling, you can ensure your application stays resilient, responsive, and cost-effective. It’s like having a magical elastic system that expands and contracts as needed, effortlessly adapting to the ever-changing demands of your application.</p>
<p>Unfortunately, this feature is exclusive to <a target="_blank" href="https://cloud.google.com/kubernetes-engine/docs/how-to/multidimensional-pod-autoscaling">Google Cloud</a> and unavailable as an open-source project.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>Tree solutions exist. The most common autoscaling is definitively horizontal autoscaling. A lot of large companies already use it, and it works well in a lot of situations. Vertical autoscaling is helpful, but limitations restrict a lot of its usage. And multidimensional may be the best, but it requires you to know your application very well when setting limits.</p>
<p>Tests are mandatory to ensure the behavior of the autoscaler is the one expected for your application!</p>
]]></content:encoded></item><item><title><![CDATA[How We Designed Qovery To Manage Thousands of Kubernetes Clusters with a Single Control Plane]]></title><description><![CDATA[Deploying and managing applications in the cloud can be complex and time-consuming, especially when using Kubernetes. However, Qovery has made this process much easier with its platform abstracts away the complexity of Kubernetes and provides develop...]]></description><link>https://www.heapstack.sh/how-we-designed-qovery-to-manage-thousands-of-kubernetes-clusters-with-a-single-control-plane</link><guid isPermaLink="true">https://www.heapstack.sh/how-we-designed-qovery-to-manage-thousands-of-kubernetes-clusters-with-a-single-control-plane</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[Devops]]></category><category><![CDATA[engineering]]></category><category><![CDATA[design and architecture]]></category><category><![CDATA[qovery]]></category><dc:creator><![CDATA[Romaric Philogène]]></dc:creator><pubDate>Sun, 16 Jul 2023 08:18:41 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1689495458475/516fc427-5eb7-4fc9-b358-a8e3f95e239e.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Deploying and managing applications in the cloud can be complex and time-consuming, especially when using Kubernetes. However, Qovery has made this process much easier with its platform abstracts away the complexity of Kubernetes and provides developers with the tools they need to manage their deployments. But how does Qovery manage thousands of Kubernetes clusters with a single control plane? In this article, we'll take a closer look at how Qovery operates Kubernetes, handles thousands of deployments per day, and what happens when the control plane is unavailable. We'll also discuss the core technology behind Qovery's control plane and how it ensures reliable and efficient management of Kubernetes clusters.</p>
<h2 id="heading-what-is-qovery">What is Qovery?</h2>
<p>Qovery is a cloud platform that simplifies the deployment of applications on Kubernetes. With Qovery, developers can focus on writing code and leave the infrastructure management to the platform. Qovery provides a better developer experience on Kubernetes by streamlining the deployment process, automating repetitive tasks, and offering an intuitive web interface and CLI for managing the deployment lifecycle.</p>
<p><img src="https://images.prismic.io/qovery/41f83ca5-3f26-4904-a326-74a863792f5a_qovery+on+top+of+kubernetes+and+cloud.png?auto=compress,format&amp;rect=0,0,1092,1612&amp;w=464&amp;h=685" alt="Qovery runs on top of Kubernetes, and on top of your cloud account." class="image--center mx-auto" /></p>
<p>Qovery is particularly useful for companies that want to leverage Kubernetes for their applications but don't have the expertise or resources to manage the infrastructure. Qovery enables companies to deploy their applications on Kubernetes with minimal effort, reducing the time and costs associated with infrastructure management.</p>
<p>Whether you're a junior, experienced, or senior developer, Qovery makes deploying your applications to the cloud using Kubernetes a breeze. Qovery abstracts away the complexity of Kubernetes, allowing developers to focus on writing code and delivering value to their customers. With Qovery, you can confidently deploy your applications, knowing that the platform takes care of the underlying infrastructure and provides the tools you need to manage your deployment. Qovery also allows access to your infrastructure and Kubernetes cluster if needed, giving you full control and flexibility over your deployment.</p>
<h2 id="heading-how-kubernetes-is-operated">How Kubernetes is operated</h2>
<p>Qovery uses a unique architecture to manage thousands of Kubernetes clusters with a single control plane. The control plane is a core component of Kubernetes that manages the state of the cluster and communicates with the API server to perform operations such as deploying and scaling applications. In Qovery's case, the control plane is written in Rust and Kotlin and handles API requests from Git providers and web and CLI interfaces. The control plane then interprets, transforms, and forwards the requests to the appropriate Kubernetes cluster.</p>
<p><img src="https://images.prismic.io/qovery/07a8b688-903d-45b5-b290-b5b419540eb4_How+Qovery+Can+Manages+Thousands+of+Kubernetes+Clusters+with+a+Single+Control+Plane+-+1.png?auto=compress,format" alt="The most significant part of the Qovery Control Plane is written in Kotlin, but we have satellite services (not represented here) written in Rust" class="image--center mx-auto" /></p>
<p><em>The most significant part of the Qovery Control Plane is written in Kotlin, but we have satellite services (not represented here) written in Rust</em></p>
<p>On the customer side, Qovery runs a set of binaries, including the Engine and Agent, that handle requests from the control plane and execute tasks. Each Kubernetes cluster managed by Qovery is autonomous and does not rely on Qovery Control Plane. This means that in case of a failure of the Qovery control plane or any Qovery components, the customer infrastructure and Kubernetes cluster are not impacted.</p>
<p><img src="https://images.prismic.io/qovery/c03fab4e-15a3-4ff3-b997-ff3affcb5680_How+Qovery+Can+Manages+Thousands+of+Kubernetes+Clusters+with+a+Single+Control+Plane+-+2.png?auto=compress,format" alt="Qovery Engine pulls tasks from the Qovery Control Plane and executes those tasks on the Kubernetes cluster. Note that the Qovery Engine intiates the connection to the Qovery Control Plane." class="image--center mx-auto" /></p>
<p><em>Qovery Engine pulls tasks from the Qovery Control Plane and executes those tasks on the Kubernetes cluster. Note that the Qovery Engine initiates the connection to the Qovery Control Plane.</em></p>
<p>Qovery's unique architecture enables horizontal scaling out of the box, as each Kubernetes cluster is independent and only picks up instructions from the control plane to execute. This means that the Qovery control plane does not need to scale, and the only resource consumption on Qovery is the stream flow of events when a deployment happens.</p>
<p><img src="https://images.prismic.io/qovery/49c5773b-2aba-45be-8cf4-6e5410b2db5a_How+Qovery+Can+Manages+Thousands+of+Kubernetes+Clusters+with+a+Single+Control+Plane+-+3.png?auto=compress,format" alt="Metadata are sent over gRPC/TLS " class="image--center mx-auto" /></p>
<p><em>Metadata is sent over gRPC/TLS</em></p>
<p>Qovery receives metadata on deployment information, which it handles to manage the state and report what happened to the user.</p>
<h3 id="heading-handling-thousands-of-kubernetes-clusters">Handling Thousands of Kubernetes Clusters</h3>
<p>When a deployment occurs, metadata is sent from the Qovery Engine and Agent to the control plane. This metadata includes information such as the application name, version, environment, and other details that are relevant to the deployment.</p>
<p><img src="https://images.prismic.io/qovery/0fcaf433-9b7c-477c-8ea6-849dace7b3a8_How+Qovery+Can+Manages+Thousands+of+Kubernetes+Clusters+with+a+Single+Control+Plane+-+4.png?auto=compress,format" alt="Thousands of Kubernetes clusters can be connected to the Qovery Control Plane" class="image--center mx-auto" /></p>
<p><em>Thousands of Kubernetes clusters can be connected to the Qovery Control Plane</em></p>
<p>Here's an example of what the metadata payload looks like:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"type"</span>: <span class="hljs-string">"info"</span>,
  <span class="hljs-attr">"timestamp"</span>: <span class="hljs-string">"2023-03-02T07:59:44.405961310Z"</span>,
  <span class="hljs-attr">"details"</span>: {
    <span class="hljs-attr">"pool_id"</span>: <span class="hljs-string">"4ceb7649-ed84-4c52-a27b-e7fca06afaaa"</span>,
    <span class="hljs-attr">"organization_id"</span>: <span class="hljs-string">"141c07cc-0dd9-4623-9999-3fdd61867555"</span>,
    <span class="hljs-attr">"cluster_id"</span>: <span class="hljs-string">"a8ad0659-bbbb-4c83-ad77-092e97bb2cae"</span>,
    <span class="hljs-attr">"execution_id"</span>: <span class="hljs-string">"fba2ac8b-6f78-4444-85c2-b137981056ff-65-1677743982"</span>,
    <span class="hljs-attr">"stage"</span>: {
      <span class="hljs-attr">"step"</span>: <span class="hljs-string">"PreCheck"</span>
    },
    <span class="hljs-attr">"transmitter"</span>: {
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"Environment"</span>,
      <span class="hljs-attr">"id"</span>: <span class="hljs-string">"fba2ac8b-6f78-430f-85c2-b1379810ffff"</span>,
      <span class="hljs-attr">"name"</span>: <span class="hljs-string">"production"</span>
    }
  },
  <span class="hljs-attr">"error"</span>: <span class="hljs-literal">null</span>,
  <span class="hljs-attr">"message"</span>: {
    <span class="hljs-attr">"safe_message"</span>: <span class="hljs-string">"\uD83C\uDFC1 Deployment request fba2ac8b-6f78-430f-85c2-b137981056ff-65-1677743982 for stage 1 `first stage` has been sent to the engine"</span>,
    <span class="hljs-attr">"full_details"</span>: <span class="hljs-literal">null</span>
  }
}
</code></pre>
<p>One payload like this represents one line into the Qovery deployment console (like below)</p>
<p><img src="https://images.prismic.io/qovery/3dbeb4fd-74ab-4f89-8e34-eada04a5a4ad_CleanShot+2023-03-02+at+10.08.06.png?auto=compress,format" alt="Deployment logs view from the Qovery Web Console" class="image--center mx-auto" /></p>
<p><em>Deployment logs view from the Qovery Web Console</em></p>
<p>By managing thousands of deployments per day (and growing steadily), we receive hundreds of thousands of metadata like the one below, which is relatively compact. Despite the high volume of deployments, Qovery's control plane performance is not impacted, as there is no transformation on the control plane side. Simple ingestion.</p>
<p><img src="https://images.prismic.io/qovery/043ada78-22f5-4bd7-9bfd-99701ebde940_grafana+core.png?auto=compress,format" alt="Most of the Qovery Control Plane operations are handled by what we call the Core - written in Kotlin (JVM based). Here is the Core load average on the last 30 days. Each sliced color is a new release of the Core." class="image--center mx-auto" /></p>
<p>Most of the Qovery Control Plane operations are handled by what we call the Core - written in Kotlin (JVM based). Here is the Core load average for the last 30 days. Each sliced color is a new release of the Core.</p>
<p>This means that Qovery can handle large-scale deployments with ease without worrying. Simplicity is key.</p>
<h2 id="heading-core-control-plane-configuration">Core Control Plane configuration</h2>
<p>Most of the Qovery Control Plane operations are handled by what we call the Core, written in <a target="_blank" href="https://kotlinlang.org/">Kotlin</a> (I will explain why we decided to use it in a future article). The Core runs on an instance in the AWS us-east-2 region with 4GB of RAM and 4vCPU. This instance uses the v17 LTS version of the JVM (Java Virtual Machine) and Kotlin 1.8.</p>
<h2 id="heading-qovery-control-plane-availability">Qovery Control Plane Availability</h2>
<p>Availability is one of the most important aspects of any cloud infrastructure, and Qovery is no exception. While Qovery's control plane is essential for managing Kubernetes clusters, it's important to note that the infrastructure still runs even if the control plane is unavailable.</p>
<p><img src="https://images.prismic.io/qovery/a9c0690b-a924-4a5f-bd4f-9b6ab73101d5_How+Qovery+Can+Manages+Thousands+of+Kubernetes+Clusters+with+a+Single+Control+Plane+-+5.png?auto=compress,format" alt="Kubernetes clusters keep running without any downtime even if they no longer can connect to the Qovery Control Plane" class="image--center mx-auto" /></p>
<p>Kubernetes clusters keep running without any downtime even if they no longer can connect to the Qovery Control Plane</p>
<p>When the Qovery control plane is unavailable, it's no longer possible to deploy applications or updates via Qovery. However, the infrastructure remains fully functional and independent since each Kubernetes cluster is autonomous and does not rely on Qovery.</p>
<p><img src="https://images.prismic.io/qovery/fe9d2d58-4fdc-432c-a19a-1e04ec57ef3d_zlLydol7ndM7C.gif?auto=compress,format" alt="Sometimes it's just better to wait and expect it will work again... 😅" class="image--center mx-auto" /></p>
<p>Sometimes it's just better to wait and expect it will work again... 😅</p>
<p>To use an analogy, the relationship between a TV and a remote control is similar to that between Qovery and the remote Kubernetes clusters it manages. If your TV remote control has no more battery, your TV will keep running, but you won't be able to change the current channel until you replace the batteries. Similarly, if the Qovery control plane is unavailable, the infrastructure keeps running, but you won't be able to use Qovery to deploy new updates or make changes until the control plane is back up and running.</p>
<p><em>If you are curious about our reliability, check out our</em> <a target="_blank" href="https://status.qovery.com"><em>status page</em></a> <em>😄</em></p>
<h2 id="heading-wrapping-up">Wrapping up</h2>
<p>Qovery is a robust platform that simplifies Kubernetes cluster management and empowers developers to deploy and update their applications easily. The unique architecture of a single control plane allows Qovery to handle thousands of autonomous Kubernetes clusters worldwide while maintaining cluster autonomy ensure that infrastructure remains operational even in the event of a control plane interruption.</p>
<p>By providing a seamless developer experience, Qovery enables developers of all levels to manage their applications easily. Its reliability and scalability give them peace of mind to focus on their code and development work.</p>
<p>Our upcoming article will explore how Qovery manages the upgrade and maintenance of Kubernetes clusters at scale. Stay tuned to learn more about how Qovery can help developers streamline their workflows and focus on what matters most - building great applications.</p>
<p>Resources:</p>
<ul>
<li><p><a target="_blank" href="https://github.com/Qovery/engine">Qovery Engine code (GitHub)</a></p>
</li>
<li><p><a target="_blank" href="https://www.qovery.com/blog/how-we-built-qovery---part-1">How we built Qovery - Part I</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Understanding the Basics of Application Autoscaling]]></title><description><![CDATA[Application autoscaling is a considerable subject. At first, it looks simple because everyone understands the goal and how conceptually it works, but it’s not that simple in practice.
Let’s start with a simple schema explaining what type of app auto-...]]></description><link>https://www.heapstack.sh/understanding-the-basics-of-application-autoscaling</link><guid isPermaLink="true">https://www.heapstack.sh/understanding-the-basics-of-application-autoscaling</guid><category><![CDATA[Devops]]></category><category><![CDATA[Developer]]></category><category><![CDATA[Kubernetes]]></category><dc:creator><![CDATA[Romaric Philogène]]></dc:creator><pubDate>Sat, 15 Jul 2023 19:02:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1689448673269/e755f6d1-cc79-4083-bac2-0165ff0cbaf0.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Application autoscaling is a considerable subject. At first, it looks simple because everyone understands the goal and how conceptually it works, but it’s not that simple in practice.</p>
<p>Let’s start with a simple schema explaining what type of app auto-scaling exists today:</p>
<p><img src="https://images.prismic.io/qovery/d02c672f-db22-446f-acbc-ba431c4fd11a_Autoscaling.png?auto=compress,format" alt="Horizontal Autoscaling vs. Vertical Autoscaling vs. Multi-dimensional Autoscaling" class="image--center mx-auto" /></p>
<p>At <a target="_blank" href="https://www.qovery.com">Qovery</a>, we’re using horizontal and vertical autoscaling on a daily basis for our production at different levels, and the result is excellent when the tuning is made after days/weeks of statistics, analysis, and configuration.</p>
<p><img src="https://images.prismic.io/qovery/ca729899-20e0-4a5a-a305-afed91535b74_graf.png?auto=compress,format" alt="Graph of Qovery Engine autoscaling triggered" class="image--center mx-auto" /></p>
<h2 id="heading-horizontal-autoscaling">Horizontal autoscaling</h2>
<p><img src="https://images.prismic.io/qovery/0c55d4d8-263e-4978-9b7f-1d9acb9aee1e_horizontal+autoscaling.png?auto=compress,format" alt="Horizontal Autoscaling" class="image--center mx-auto" /></p>
<p>Horizontal autoscaling is scaling up an application by adding more app instances to distribute the workload across all instances, allowing for increased capacity and improved performance.</p>
<p><em><mark>Application autoscaling is different than cluster autoscaling, but it's somehow related. In the context where your app runs on a cluster (E.g., Kubernetes), the more your app scales up the number of instances, the more your app is likely to consume cluster resources, and the more the cluster is likely to scale up nodes.</mark></em></p>
<p>Horizontal scaling refers to automatically adding or removing instances based on predefined rules or metrics. When the workload increases, additional instances are dynamically provisioned to handle the increased demand. Conversely, excess instances are automatically terminated when the workload decreases to optimize resource utilization and cost.</p>
<p>Horizontal autoscaling offers several benefits, including:</p>
<ul>
<li><p><strong>Improved performance</strong>: By distributing the workload across multiple instances, horizontal scaling can handle increased traffic or resource-intensive tasks more effectively, reducing response times and improving overall performance.</p>
</li>
<li><p><strong>Enhanced availability</strong>: Additional instances provide redundancy and fault tolerance. If one instance fails or becomes overloaded, the load can be automatically distributed to other instances, ensuring uninterrupted service availability.</p>
</li>
<li><p><strong>Scalability</strong>: Horizontal scaling allows for seamless expansion of an application or system by adding more instances. This flexibility enables businesses to accommodate sudden surges in traffic or increased demand without impacting performance.</p>
</li>
<li><p><strong>Cost optimization</strong>: Autoscaling allows you to allocate resources based on actual demand. Scaling up or down based on workload ensures efficient resource utilization, preventing overprovisioning and reducing unnecessary costs.</p>
</li>
</ul>
<h2 id="heading-vertical-autoscaling">Vertical autoscaling</h2>
<p><img src="https://images.prismic.io/qovery/1f998e32-2747-4a79-8e0f-b49d275d611b_vertical+Autoscaling.png?auto=compress,format" alt="Vertical Autoscaling" class="image--center mx-auto" /></p>
<p>Vertical autoscaling is a way to make your application more resource-autonomous by upgrading the resources of a single application instead of adding more machines (and scaling horizontally). It's like boosting your computer by increasing its CPU power, memory, storage, or network capacity.</p>
<p>With vertical autoscaling, you can improve your application's performance without the need to manage many instances. It simplifies administration and reduces the complexity of handling a distributed system.</p>
<p>However, there's a maximum limit to how much you can upgrade an instance before hitting hardware constraints. Also, scaling up or down vertically may require restarting or reconfiguring the machine, resulting in temporary downtime or disruption.</p>
<p>Vertical autoscaling is commonly used in traditional setups or when the workload can't be easily distributed across multiple instances. It's handy for applications that require a lot of computational power, memory, or specialized hardware configurations.</p>
<p>Although horizontal autoscaling has gained popularity with cloud computing and containers, vertical autoscaling still plays a role in optimizing the performance and resource utilization of individual instances in specific situations.</p>
<h2 id="heading-multidimensional-autoscaling-google-proprietary">Multidimensional autoscaling (Google proprietary)</h2>
<p><img src="https://images.prismic.io/qovery/be25687f-3f73-4573-af10-880759e988b0_multi-dimensional+Autoscaling.png?auto=compress,format" alt="Multi-dimensional Autoscaling" class="image--center mx-auto" /></p>
<p>Multidimensional autoscaling is like having a super-smart system that automatically adjusts the resources of your application or system in multiple dimensions to handle changing demands. It's all about ensuring your application has the right power and capacity when needed.</p>
<p>Think of it as a dynamic team of helpers that can scale up or down in terms of the number of instances and by upgrading or downgrading the resources within each instance. It's like giving your application a turbo boost or dialing it down when the workload changes.</p>
<p>With multidimensional autoscaling, you don't have to adjust resources or add more instances manually. The system takes care of it for you, continuously monitoring metrics like CPU usage, memory, network traffic, or any other custom-defined criteria.</p>
<p>When your application is experiencing high traffic or increased resource demands, multidimensional autoscaling will intelligently add more resources to ensure smooth performance and prevent any slowdowns or crashes. On the other hand, when the workload decreases, it will automatically scale down to optimize resource usage and save costs.</p>
<p>The beauty of multidimensional autoscaling is that it considers multiple factors to make the right decisions. It's like having a super-smart teammate who knows when to boost your application and when to hold back to avoid wasting resources.</p>
<p>By employing multidimensional autoscaling, you can ensure your application stays resilient, responsive, and cost-effective. It's like having a magical elastic system that expands and contracts as needed, effortlessly adapting to the ever-changing demands of your application.</p>
<p>Unfortunately, this feature is exclusive to <a target="_blank" href="https://cloud.google.com/kubernetes-engine/docs/how-to/multidimensional-pod-autoscaling">Google Cloud</a> and unavailable as an open-source project.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>Tree solutions exist. The most common autoscaling is definitively horizontal autoscaling. A lot of large companies already use it, and it works well in a lot of situations. Vertical autoscaling is helpful, but limitations restrict a lot of its usage. And multidimensional may be the best, but it requires you to know your application very well when setting limits.</p>
<p>Tests are mandatory to ensure the behavior of the autoscaler is the one expected for your application!</p>
]]></content:encoded></item><item><title><![CDATA[The ultimate guide to migrate from Heroku to AWS in 1 hour]]></title><description><![CDATA[This guide describes how to migrate your application running on Heroku to AWS with Qovery. It covers all the required steps you need to take to deploy your application on AWS and transfer your data from Heroku Postgres to the database managed by AWS....]]></description><link>https://www.heapstack.sh/the-ultimate-guide-to-migrate-from-heroku-to-aws-in-1-hour</link><guid isPermaLink="true">https://www.heapstack.sh/the-ultimate-guide-to-migrate-from-heroku-to-aws-in-1-hour</guid><category><![CDATA[Heroku]]></category><category><![CDATA[AWS]]></category><category><![CDATA[migration]]></category><category><![CDATA[PostgreSQL]]></category><category><![CDATA[Docker]]></category><dc:creator><![CDATA[Romaric Philogène]]></dc:creator><pubDate>Sat, 21 May 2022 12:44:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1653136999590/rjvUFyEyg.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This guide describes how to migrate your application running on Heroku to AWS with <a target="_blank" href="https://www.qovery.com">Qovery</a>. It covers all the required steps you need to take to deploy your application on AWS and transfer your data from Heroku Postgres to the database managed by AWS.</p>
<blockquote>
<p><em>Qovery is a platform used by more than 22 000 developers to deploy their apps on their AWS accounts. It's the "Heroku-like" experience on top of AWS.</em></p>
</blockquote>
<p>This is the final result 😎</p>
<p><a href="https://www.loom.com/share/da31c21f9c104eae9270e4c4db59055e">
    <img src="https://cdn.loom.com/sessions/thumbnails/da31c21f9c104eae9270e4c4db59055e-with-play.gif" />
</a></p>
<h2 id="heading-assumptions">Assumptions 👨‍🏫</h2>
<ul>
<li>You have an application on Heroku</li>
<li>You are familiar with Heroku basics, have a Heroku account and access to Heroku CLI</li>
<li>You have <a target="_blank" href="https://start.qovery.com">sign in on Qovery</a></li>
<li>You have <a target="_blank" href="https://hub.qovery.com/guides/tutorial/how-to-deploy-your-application-on-aws-in-30-minutes/">set up your AWS account</a> with Qovery</li>
</ul>
<h2 id="heading-costs">Costs 💵</h2>
<ul>
<li>Qovery installs an EC2 instance (perfect for hobby project) or an EKS cluster (perfect for production) on your AWS account.</li>
<li>Qovery is free up to 100 deployments/month (see <a target="_blank" href="https://www.qovery.com/pricing">pricing</a>)</li>
</ul>
<h2 id="heading-migration-steps">Migration Steps 🪜</h2>
<ol>
<li>Use Buildpacks or Create your Dockerfile</li>
<li>Create resources on Qovery</li>
<li>Configure Environment Variables and Secrets</li>
<li>Copy data from your Heroku databases to your AWS databases</li>
<li>Deploy your apps</li>
<li>FAQ by Heroku users</li>
</ol>
<h2 id="heading-1-create-your-dockerfile-or-use-buildpacks">1. Create your Dockerfile or Use Buildpacks 🍃</h2>
<p>Qovery supports two ways to build and run your application coming from Heroku:</p>
<ol>
<li>Buildpacks</li>
<li>Docker</li>
</ol>
<p>Both options build a container image that is runnable by a container engine (E.g. Docker). Qovery runs containers on Kubernetes.</p>
<blockquote>
<p>I will explain how to use Buildpacks. Refer to <a target="_blank" href="https://hub.qovery.com/guides/tutorial/migrate-your-application-from-heroku-to-aws/#1-create-your-dockerfile-or-use-buildpacks">the original guide</a> to get instructions to use a Dockerfile.</p>
</blockquote>
<p><a target="_blank" href="https://buildpacks.io/">Buildpacks</a> automatically detects the language and the framework your application is using. Buildpacks builds and runs your app. Here is the list of <a target="_blank" href="https://hub.qovery.com/docs/using-qovery/configuration/application/#option-1-buildpacks">supported languages and frameworks</a>.</p>
<p><strong>Supported languages</strong></p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>language</td><td>version</td></tr>
</thead>
<tbody>
<tr>
<td>Node.JS</td><td>any</td></tr>
<tr>
<td>Clojure</td><td>any</td></tr>
<tr>
<td>Python</td><td>any</td></tr>
<tr>
<td>Java</td><td>any</td></tr>
<tr>
<td>Gradle</td><td>any</td></tr>
<tr>
<td>JVM</td><td>any</td></tr>
<tr>
<td>Grails</td><td>any</td></tr>
<tr>
<td>Scala</td><td>any</td></tr>
<tr>
<td>Play</td><td>any</td></tr>
<tr>
<td>PHP</td><td>any</td></tr>
<tr>
<td>Go</td><td>any</td></tr>
</tbody>
</table>
</div><hr />
<p>⚠️ We do recommend using Docker to keep the full control of what's going on behind the scene. Buildpacks is a great technology but difficult to debug when something goes wrong. You can try deploying your apps on AWS with Qovery with Buildpacks, if you do not succeed, we do recommend switching for Docker.</p>
<hr />
<h3 id="heading-limitations">Limitations 👀</h3>
<p>Here are some limitations due to our Buildpacks implementation:</p>
<ul>
<li>Qovery Buildpacks does not support Procfile with multiple commands at the moment.</li>
<li>Qovery does not support custom Buildpacks.</li>
</ul>
<p>Those limitations will be solved in the coming months.</p>
<h2 id="heading-2-create-resources-on-qovery">2. Create resources on Qovery 👩‍💻</h2>
<h3 id="heading-application">Application</h3>
<p><a href="https://www.loom.com/share/9246ae68c68f42debc3d5183d2b4f7f8">
    <img src="https://cdn.loom.com/sessions/thumbnails/9246ae68c68f42debc3d5183d2b4f7f8-with-play.gif" />
</a></p>
<p>Steps:</p>
<ol>
<li>Connect to the <a target="_blank" href="https://start.qovery.com">Qovery console</a>.</li>
<li>Create your <a target="_blank" href="https://hub.qovery.com/docs/using-qovery/configuration/organization/">Organization</a> and your <a target="_blank" href="https://hub.qovery.com/docs/using-qovery/configuration/project/">Project</a>.</li>
<li>Create an environment with the name <code>production</code> (it can be changed after).</li>
<li>Create an application and give it a name (you can give the name of your repo if you have no idea)</li>
<li>Select your app repository from your GitHub, GitLab or Bitbucket.</li>
<li>Select the branch you want to deploy.</li>
<li>Select the Build mode for <code>Buildpacks</code> or <code>Dockerfile</code> according to what you want.</li>
<li>Specify the local listening port of your application.</li>
<li>Click on "create"</li>
</ol>
<p>Congrats! Your application is created 🎉</p>
<hr />
<p>⚠️ Your application is created but not deployed yet! You can configure the vCPU, Memory, Environment Variables... before deploying it. If you want to deploy it before finishing the configuration you can click on "Actions" &gt; "Deploy".</p>
<hr />
<p>If you deploy an app from a mono-repository, we have a must-read guide for you <a target="_blank" href="https://hub.qovery.com/guides/advanced/monorepository/">here</a>.</p>
<h3 id="heading-database">Database ⚡️</h3>
<p>Here are the steps to deploy your database:</p>
<p><a href="https://www.loom.com/share/d7e10be0e5964f6799b158dc631bbbd1">
    <img src="https://cdn.loom.com/sessions/thumbnails/d7e10be0e5964f6799b158dc631bbbd1-with-play.gif" />
</a></p>
<p>Steps:</p>
<ol>
<li>Go to your <code>production</code> environment.</li>
<li>Add your database by clicking on "Add" &gt; "Database".</li>
<li>Select the database (PostgreSQL, MySQL, MongoDB, Redis..) and the version you want to deploy.</li>
<li>Select <a target="_blank" href="https://hub.qovery.com/docs/using-qovery/configuration/database/#modes">Managed or Container mode</a> for your database.</li>
<li>Select <code>Public</code> accessibility (set <code>Private</code> if you don't want to restore your data from an existing Heroku database).</li>
</ol>
<p>Congrats! Your database is created as well 🎉</p>
<p>If you use MongoDB Atlas, or an existing database on AWS that you want to connect to your application deployed by Qovery. Check out <a target="_blank" href="https://hub.qovery.com/guides/tutorial/aws-vpc-peering-with-qovery/">our tutorial about VPC peering</a> and how to securely connect to your existing database.</p>
<h2 id="heading-3-configure-your-environment-variables-and-secrets">3. Configure your Environment Variables and Secrets 🛡</h2>
<p>Qovery makes the difference between an <a target="_blank" href="https://hub.qovery.com/docs/using-qovery/configuration/environment-variable">Environment Variable</a> and a <a target="_blank" href="https://hub.qovery.com/docs/using-qovery/configuration/secret/">Secret</a>. Basically, a Secret is similar to an Environment Variable but the value is encrypted and can't be revealed. Both are injected as environment variables during the build and the run of your applications.</p>
<p>To extract your environment variables from Heroku, we recommend using the <a target="_blank" href="https://devcenter.heroku.com/articles/heroku-cli">Heroku CLI</a> and exporting all the environment variables and secrets in an .env (dot env) file. Qovery supports the <a target="_blank" href="https://hub.qovery.com/guides/tutorial/import-your-environment-variables-with-the-qovery-cli/">import of a dot env file</a> via the Qovery web interface and the Qovery CLI.</p>
<hr />
<p>⚠️ If you use Buildpacks for one of your app AND you have indicated a local listening port of your application, you will need to add an environment variable <code>PORT</code> with the value of your port to make your application starting properly. Otherwise, Qovery will fail to deploy your app!</p>
<hr />
<p><a target="_blank" href="https://devcenter.heroku.com/articles/config-vars#view-current-config-var-values">Export your environment variable via the Heroku CLI</a> with the command:</p>
<pre><code class="lang-shell"># To install Heroku CLI: https://devcenter.heroku.com/articles/heroku-cli
heroku config

GREETINGS: hello world
STRIPE_API_KEY: xxx-yyy-zzz
IS_PRODUCTION: true
</code></pre>
<p>Then you can create your environment variables via the web interface (watch the video below)</p>
<p><a href="https://www.loom.com/share/50899d7fa3d84a418f0db69f54f970d3">
    <img src="https://cdn.loom.com/sessions/thumbnails/50899d7fa3d84a418f0db69f54f970d3-with-play.gif" />
</a></p>
<p>Or via the <a target="_blank" href="https://hub.qovery.com/docs/using-qovery/interface/cli/">Qovery CLI</a>:</p>
<pre><code class="lang-shell"># auth yourself
qovery auth

# selection the app where you want to import your environment variables
qovery context set

# import your Heroku environment variables
heroku config --app &lt;your_heroku_app_name&gt; --json | qovery env import --heroku-json

Qovery: Heroku environment variables import from JSON
? Do you want to import Environment Variables or Secrets? Environment Variables
? What environment variables do you want to import?  [Use arrows to move, space to select, &lt;right&gt; to all, &lt;left&gt; to none, type to filter]
  [x]  GREETINGS=hello world
  [ ]  STRIPE_API_KEY=xxx-yyy-zzz
&gt; [x]  IS_PRODUCTION=true

Qovery: ✅ Environment Variables successfully imported!
</code></pre>
<hr />
<p>⚠️ Import sensitive data (E.g. API keys, credentials...) as <code>Secret</code> and not <code>Environment Variable</code>.</p>
<hr />
<h3 id="heading-connect-your-frontend-app-to-your-backend-app">Connect your frontend app to your backend app</h3>
<p>To connect your frontend app your backend app we will create an [environment variable alias][docs.using-qovery.configuration.environment-variable#alias-environment-variable].</p>
<p>Here is how to create a frontend app:</p>
<p><a href="https://www.loom.com/share/bafbbda93bd64d04afb3189bf4a1a201">
    <img src="https://cdn.loom.com/sessions/thumbnails/bafbbda93bd64d04afb3189bf4a1a201-with-play.gif" />
</a></p>
<p>And now how to connect your frontend app with your backend app:</p>
<p><a href="https://www.loom.com/share/f820925f2175465f9271b97ef414bb42">
    <img src="https://cdn.loom.com/sessions/thumbnails/f820925f2175465f9271b97ef414bb42-with-play.gif" />
</a></p>
<p>You can also take a look at <a target="_blank" href="https://discuss.qovery.com/t/918">this forum reply</a> to learn how to do it.</p>
<h3 id="heading-connect-your-backend-app-to-your-database">Connect your backend app to your database</h3>
<p>Same as connecting your frontend app to your backend app, you can create an environment variable alias <code>DATABASE_URL</code> for the <em>built-in</em> secret finishing with <code>_DATABASE_URL_INTERNAL</code>.</p>
<hr />
<p>⚠️ Create an alias on <code>_DATABASE_URL_INTERNAL</code> and not <code>_DATABASE_URL</code></p>
<hr />
<p><a href="https://www.loom.com/share/59f8368eb3c14796a807c7e39e9c0ab0">
    <img src="https://cdn.loom.com/sessions/thumbnails/59f8368eb3c14796a807c7e39e9c0ab0-with-play.gif" />
</a></p>
<h2 id="heading-4-copy-data-from-your-heroku-databases-to-your-aws-databases">4. Copy data from your Heroku databases to your AWS databases</h2>
<p><em>Coming soon with <a target="_blank" href="https://www.replibyte.com">Replibyte</a></em></p>
<h2 id="heading-5-deploy-your-apps">5. Deploy your apps!</h2>
<p>We are finally ready to deploy my applications on AWS!</p>
<p><a href="https://www.loom.com/share/0589d2f2aa4149edb605dc23f4efd23d">
    <img src="https://cdn.loom.com/sessions/thumbnails/0589d2f2aa4149edb605dc23f4efd23d-with-play.gif" />
</a></p>
<p>Watch the final result 😎</p>
<p>https://www.loom.com/share/da31c21f9c104eae9270e4c4db59055e</p>
<h2 id="heading-faq-by-heroku-users">FAQ by Heroku users</h2>
<h3 id="heading-how-to-create-a-custom-domain">How to create a custom domain?</h3>
<p>Check out the documentation on <a target="_blank" href="https://hub.qovery.com/guides/getting-started/setting-custom-domain/">how to configure your custom domain</a>.</p>
<h3 id="heading-how-to-monitor-my-apps">How to monitor my apps?</h3>
<p>We do recommend using <a target="_blank" href="https://www.datadoghq.com">Datadog</a> or any other monitoring products for monitoring your apps deployed by Qovery. Check out <a target="_blank" href="https://hub.qovery.com/guides/tutorial/kubernetes-observability-and-monitoring-with-datadog/">our tutorial on how to install Datadog</a></p>
<h3 id="heading-do-you-have-heroku-review-app-equivalent">Do you have Heroku "Review App" equivalent?</h3>
<p>Yes, it's what we call <a target="_blank" href="https://hub.qovery.com/docs/using-qovery/configuration/environment/#preview-environment">Preview Environment</a></p>
<h3 id="heading-how-to-rollback">How to rollback?</h3>
<p>Check out the <a target="_blank" href="https://hub.qovery.com/docs/using-qovery/configuration/application/#update-and-rollback">app rollback documentation</a></p>
<h3 id="heading-how-auto-scaling-works">How auto-scaling works?</h3>
<p>Check out the <a target="_blank" href="https://hub.qovery.com/docs/using-qovery/configuration/application/#auto-scaling">app auto-scaling documentation</a></p>
<h3 id="heading-how-to-manage-database-migration">How to manage database migration?</h3>
<p>Check out <a target="_blank" href="https://discuss.qovery.com/t/951">our forum reply</a></p>
<h3 id="heading-is-it-possible-to-get-a-shell-connect-to-my-app">Is it possible to get a shell / connect to my app?</h3>
<p>Yes, with the Qovery CLI and the command <code>qovery shell</code>. <a target="_blank" href="https://hub.qovery.com/docs/using-qovery/interface/cli/#shell">Check out the documentation</a>.</p>
<h3 id="heading-can-i-use-terraform-and-infrastructure-as-code">Can I use Terraform and Infrastructure as Code?</h3>
<p>Absolutely, we have a <a target="_blank" href="https://hub.qovery.com/docs/devops/infrastructure-as-code/terraform/">Qovery Terraform provider</a> available.</p>
<h3 id="heading-how-can-i-connect-my-app-to-mongodb-atlas">How can I connect my app to MongoDB Atlas?</h3>
<p>If you use MongoDB Atlas check out <a target="_blank" href="https://hub.qovery.com/guides/tutorial/aws-vpc-peering-with-qovery/">our tutorial about VPC peering</a> and how to securely connect to your existing MongoDB Atlas database.</p>
<h3 id="heading-how-can-i-connect-my-app-to-an-aws-service-not-managed-by-qovery">How can I connect my app to an AWS service not managed by Qovery?</h3>
<p>If you want to connect your app to an AWS service not managed by Qovery, check out <a target="_blank" href="https://hub.qovery.com/guides/tutorial/aws-vpc-peering-with-qovery/">our tutorial about VPC peering</a> and how to securely connect to this AWS service.</p>
<hr />
<p>If you have a common question about Qovery, we have a more general <a target="_blank" href="https://hub.qovery.com/docs/useful-resources/faq/">FAQ section</a> available.</p>
<h2 id="heading-wrapping-up">Wrapping up 👋🏼</h2>
<p>Congrats! You have migrated from Heroku to AWS. Feel free to check out our <a target="_blank" href="https://discuss.qovery.com">forum</a> and open a thread if you have any questions.</p>
]]></content:encoded></item><item><title><![CDATA[RepliByte - an app to synchronize your cloud databases and obfuscate sensitive data]]></title><description><![CDATA[After months of experimenting with different ways of synchronizing databases, I am super excited to announce RepliByte - a simple way to synchronize cloud databases and obfuscate sensitive data - written in Rust.
As explained in the README, my primar...]]></description><link>https://www.heapstack.sh/replibyte-an-app-to-synchronize-your-cloud-databases-and-obfuscate-sensitive-data</link><guid isPermaLink="true">https://www.heapstack.sh/replibyte-an-app-to-synchronize-your-cloud-databases-and-obfuscate-sensitive-data</guid><category><![CDATA[Rust]]></category><category><![CDATA[Databases]]></category><dc:creator><![CDATA[Romaric Philogène]]></dc:creator><pubDate>Mon, 14 Mar 2022 08:16:36 GMT</pubDate><content:encoded><![CDATA[<p>After months of experimenting with different ways of synchronizing databases, I am super excited to announce <a target="_blank" href="https://github.com/Qovery/replibyte">RepliByte</a> - a simple way to synchronize cloud databases and obfuscate sensitive data - written in Rust.</p>
<p>As explained in the README, my primary motivation is to respond to a widespread need that most developers have - cloning the production database into a development database while cleaning the sensitive data. It is precisely the purpose of RepliByte.</p>
<p>I am still in the early days of development, but you can look at the code and the README. It should be clear enough to help me out in that journey, and why not contribute?!</p>
<p>At the moment, I focus on supporting Postgres, but I plan to support MySQL and MongoDB. RepliByte can support any database since I created an abstraction layer.</p>
<p>Thanks for your feedback.</p>
<p>GitHub: https://github.com/Qovery/replibyte</p>
]]></content:encoded></item><item><title><![CDATA[Join me to learn to code in Rust]]></title><description><![CDATA[I am Romaric, CEO and co-founder of Qovery. I am 12 years of experience in backend development. I am experienced in Rust, Python, Kotlin, Java, Groovy, Go, Scala. In my free time I am working on RepliByte - an open-source application written in Rust ...]]></description><link>https://www.heapstack.sh/join-me-to-learn-to-code-in-rust</link><guid isPermaLink="true">https://www.heapstack.sh/join-me-to-learn-to-code-in-rust</guid><category><![CDATA[Rust]]></category><category><![CDATA[learning]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Romaric Philogène]]></dc:creator><pubDate>Sat, 12 Mar 2022 12:23:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1647088007719/U4HUprDCK.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I am Romaric, CEO and co-founder of <a target="_blank" href="https://www.qovery.com">Qovery</a>. I am 12 years of experience in backend development. I am experienced in Rust, Python, Kotlin, Java, Groovy, Go, Scala. <strong>In my free time I am working on <a target="_blank" href="https://github.com/qovery/replibyte">RepliByte</a></strong> - an open-source application <strong>written in Rust</strong> to synchronize cloud databases. I've always enjoyed sharing my knowledge and that's why I am launching my Twitch channel to build in public RepliByte.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tfbu5ko8gzq61r4uj124.png" alt="Here is a picture of me while coding" /></p>
<p>Join me if you want:</p>
<ol>
<li>To learn to code in Rust.</li>
<li>Contribute to building an ambitious and useful project.</li>
<li>Spend a good time.</li>
</ol>
<p>My schedules:</p>
<ul>
<li>During the weekend.</li>
<li>Some day during the week.</li>
</ul>
<p>Here is my <a target="_blank" href="https://www.twitch.tv/codewithromaric">Twitch</a>.</p>
<p>I can't wait to see you there. Let me know in the comment what you would like to learn about Rust.</p>
]]></content:encoded></item><item><title><![CDATA[How I imagine the future of databases in the Cloud]]></title><description><![CDATA[Since I launched my company, I am obsessed with how my team and I can make the cloud easier for anyone. How can we help developers and businesses to deploy their apps as fast as possible in the cloud? Regardless of the specificities of the cloud serv...]]></description><link>https://www.heapstack.sh/how-i-imagine-the-future-of-databases-in-the-cloud</link><guid isPermaLink="true">https://www.heapstack.sh/how-i-imagine-the-future-of-databases-in-the-cloud</guid><category><![CDATA[Cloud]]></category><category><![CDATA[Databases]]></category><category><![CDATA[AWS]]></category><category><![CDATA[PostgreSQL]]></category><category><![CDATA[Redis]]></category><dc:creator><![CDATA[Romaric Philogène]]></dc:creator><pubDate>Thu, 13 May 2021 09:10:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1620864251886/nWhkFB_vP.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Since I launched <a target="_blank" href="https://www.qovery.com">my company</a>, I am obsessed with how my team and I can make the cloud easier for anyone. How can we help developers and businesses to deploy their apps as fast as possible in the cloud? Regardless of the specificities of the <a target="_blank" href="https://searchitchannel.techtarget.com/definition/cloud-service-provider-cloud-provide">cloud service provider</a> (CSP). How can we remove the unnecessary complexity of the cloud for most businesses? How can we build the future of the cloud? It is the obsession that I have, and I want to share my thoughts with you on how we can make the Cloud a better place for databases.</p>
<p>The most complex integration that we faced when supporting a new CSP is the database*. A database needs to be performant, resilient, and available 24/7. Each CSP has its own constraints and way to make it works. They do not support the same number of features and the same quality of service. </p>
<blockquote>
<p>*I am talking about Open-Source databases like PostgreSQL, MySQL, and Redis. Not proprietary ones like Google Big Query and AWS DynamoDB.</p>
</blockquote>
<p>For instance, we recommend using AWS RDS in production for PostgreSQL because the reliability and quality are excellent. On the other hand, we prefer to recommend Digital Ocean when the database is for the development or non-mission-critical projects - because it is reliable enough and cheaper than AWS RDS.</p>
<blockquote>
<p>Note: <a target="_blank" href="https://kubernetes.io/">Kubernetes</a> is doing an amazing job to abstract the compute part - this is the standard defacto to run stateless applications - meaning, applications without data. However, running applications with data in a homogenous way across CSPs is still a huge challenge.</p>
</blockquote>
<p>So, how can we make database management simpler for the next decade? Let me first show you how applications are built in 2021. </p>
<h2 id="how-applications-are-built-in-2021">How applications are built in 2021</h2>
<p>If you look at the last tech topics in the last 10 years on Hackernews, Hashnode, and Reddit, you will massively hear about API, jam stack, serverless, NodeJS, Django, Rails, and other fancy names. Do you know what they have in common? The Web! Today, most developers are "web developers". We spent time building web API (GraphQL, REST, or Soap for the oldest :)), and we expose those APIs to other services. </p>
<blockquote>
<p>We live in a world where developing an application means consuming and providing web APIs.</p>
</blockquote>
<p>To build our applications, we also consume APIs like Stripe for payment, Auth0 for authentication, Chargebee for subscription, Intercom for customer support, Sqreen for app security, Datadog for monitoring, and Qovery for app deployment. We live in a world where developing an application means consuming and providing web APIs. So why do we still build backend applications like if we were in 2010?</p>
<h2 id="nothing-has-changed-in-the-last-10-years">Nothing has changed in the last 10 years</h2>
<p>When I started to work as a system engineer in 2010 and today as a developer in 2021, I saw a lot of things that have changed like:</p>
<ul>
<li>how we deploy an application with Docker and orchestrate it in the Cloud instead of using VMs with on-premise servers. </li>
<li>how the frontend is now so powerful that you don't even need to rely on a backend to build a powerful website - static website and framework is the new norm. </li>
<li>how you can scale almost to the infinite your compute workload in the Cloud. </li>
</ul>
<p>This is crazy how things have changed - and for a better developer experience and productivity for companies. But on the other hand, I don't feel that the backend world has changed so much. </p>
<blockquote>
<p>We are building backend applications in 2021, like building back-end applications in 2010.</p>
</blockquote>
<p>We have new fancy frameworks like Quarkus in Java that make you able to build native code from the JVM; we have the functional programming that has gained in popularity in the last 8 years, we have NoSQL that was "supposed" to replace SQL, microservices, reactive programming and a few other fun concepts. But in the end, we are building back-end applications in 2021, like building back-end applications in 2010. Some of you probably think it is wrong, but let me explain why it is not.</p>
<h2 id="what-is-the-problem-with-databases">What is the problem with databases</h2>
<p>I never built a back-end application that did not require using a database in my developer's life. To be honest, it happens once. When I had to create an API gateway to send push notifications to Apple APNS and Google FCM, 🙄 that's it. And I think most of us as backend developers are 99% of the time using a database to fetch and store data.</p>
<p>Databases like PostgreSQL, Redis, MongoDB, MySQL, SQLServer are robust product with tons of engineering behind. They are reliable, highly performant, and stable for most businesses. However, those databases have been designed before the Cloud was a thing. Do you remember when you had to rack your servers? :) Yes, that was the time most of the databases that we are daily using were designed. Those databases require to have a dedicated container/VM/server instance to run perfectly. My concern is: why in 2021 we do we need to dedicate CPU, memory, and storage to a database while we build web applications that will store a limited amount of data? As said before, does your app need an authentication system? Use Auth0 (now Okta). Does your app need to accept payments? Use Stripe. Does your app need to store photos? Use AWS S3... In the end, it only remains your business data in your database. So, do we need a sledgehammer to kill a gnat? 🤔</p>
<h2 id="how-to-bring-a-better-database-experience-for-backend-developers">How to bring a better database experience for backend developers</h2>
<p>I am obsessed with simplifying the lives of developers. Building and deploying applications should be simpler than what it is today - and for anyone. One true source of inspiration to me in terms of developer experience was <a target="_blank" href="https://vercel.com">Vercel</a>. Vercel turns developer experience (DX) from the app development to the deployment for frontend developers so smooth that even developers freshly out of Bootcamp know about their products. So here is my plan on how to bring a better database experience for backend developers.</p>
<h3 id="database-as-a-library">Database as a library</h3>
<p>Using a database should be as easy as using any external library. Using your favorite dependency manager, and then you are ready to go. </p>
<pre><code class="lang-bash"><span class="hljs-comment"># Install PostgreSQL for NodeJS</span>
npm install postgresql-server
</code></pre>
<pre><code class="lang-bash"><span class="hljs-comment"># Intall PostgreSQL for Python</span>
pip install postgresql-server
</code></pre>
<h3 id="no-code-change">No code change</h3>
<p>Once the library is installed, you can use the driver to connect to your local in-memory database without any change.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> { Pool, Client } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'pg'</span>);

<span class="hljs-comment">// URI to connect to your PostgreSQL instance</span>
<span class="hljs-keyword">const</span> connectionString = <span class="hljs-string">'postgresql://postgres:postgres@localhost/postgres'</span>;

<span class="hljs-keyword">const</span> pool = <span class="hljs-keyword">new</span> Pool({
  connectionString,
});

<span class="hljs-comment">// ...</span>
<span class="hljs-comment">// exec postgresql requests</span>
<span class="hljs-comment">// ....</span>
</code></pre>
<h3 id="built-for-the-cloud">Built for the Cloud</h3>
<p>The Cloud allows your applications to be run anywhere and in a very scalable way. That's why my vision for the future database is to automatically discover the neighbor instances to share data and scale horizontally. And persist the data into an object storage service that is S3 API compatible like AWS S3, Digital Ocean Spaces, Scaleway Object Storage, Google Cloud Storage, etc... A good example of this kind of implementation is  <a target="_blank" href="https://github.com/grafana/loki">Grafana Loki</a>, where all logs are stored into the Object Storage of your choice. You can read their interesting <a target="_blank" href="https://docs.google.com/document/d/11tjK_lvp1-SVsFZjgOTr1vV3-q6vBAsZYIQ5ZeYBkyM/view">design doc</a>.</p>
<h3 id="consistent-testability">Consistent testability</h3>
<p>Getting a database as a library will provide consistent behavior. Where your app runs, your database is accessible. So on your laptop, your teammate computer, your smartphone, and in the Cloud. </p>
<p>This is a dream, but this dream can be a reality. That's why I have initiated a project called RedisLess, to see how we can build a better database experience for modern backend developers. </p>
<h2 id="an-experiment-redisless-a-keyvalue-store-library-redis-api-compatible">An experiment: RedisLess - a Key/Value store library - Redis API compatible</h2>
<blockquote>
<p>RedisLess is an experiment for the database of the future.</p>
</blockquote>
<p><a target="_blank" href="https://github.com/Qovery/redisless">RedisLess</a> is an experiment to provide a fast, lightweight, embedded, and scalable in-memory Key/Value store library compatible with the Redis API. This project aims to check the feasibility of the principle listed above, and in a few days of works we succeed to have:</p>
<ul>
<li>Transparent for the developer</li>
<li>No Redis server required</li>
</ul>
<p>The remaining steps are:</p>
<ul>
<li>Supporting auto-discovery.</li>
<li>Supporting data sharing between instances.</li>
<li>Supporting persistence.</li>
</ul>
<p>As a developer, you don't need to change a single line of code to use RedisLess. And this is only the beginning. What about creating the same abstraction for PostgreSQL, MySQL, and most popular databases?</p>
<hr />
<p>Special thanks to our contributors ❤️</p>
<p><a href="https://github.com/Qovery/RedisLess/graphs/contributors">
  <img src="https://contrib.rocks/image?repo=Qovery/RedisLess" />
</a></p>
<hr />
<h2 id="why-all-of-that-matters">Why all of that matters</h2>
<p>I believe in the idea of building backend applications without having to think about how data are stored, backed up, available across multiple instances. Can't we bring for the next decade a simpler way to design databases for modern applications? This is my obsession, and if you are interested in learning more and contributing somehow, please contact me on <a target="_blank" href="https://discord.qovery.com">my discord</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Why you should code in Rust in 2021]]></title><description><![CDATA[Rust is one of the  most loved languages  by developers for 5 years - writing code in Rust will push you to be a better developer even if you will never use it in your daily job. In this article, I explain why you should learn to write code in Rust. ...]]></description><link>https://www.heapstack.sh/why-you-should-code-in-rust-in-2021</link><guid isPermaLink="true">https://www.heapstack.sh/why-you-should-code-in-rust-in-2021</guid><category><![CDATA[Rust]]></category><category><![CDATA[programming languages]]></category><category><![CDATA[trends]]></category><dc:creator><![CDATA[Romaric Philogène]]></dc:creator><pubDate>Wed, 05 May 2021 14:45:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1620205973703/ud_dKsDE3.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Rust is one of the  <a target="_blank" href="https://stackoverflow.blog/2020/06/05/why-the-developers-who-use-rust-love-it-so-much/">most loved languages</a>  by developers for 5 years - writing code in Rust will push you to be a better developer even if you will never use it in your daily job. In this article, I explain why you should learn to write code in Rust. Let's go.</p>
<h1 id="better-understanding-of-memory-management">Better understanding of memory management</h1>
<p>I remember the time I used to learn to program in Python. Memory was managed by the language, and I didn't need to understand how things work. Grasping algorithmic and all basic concepts when you are a beginner takes time. So spending time thinking about how to manage memory allocation is meaningless. But once you are fluent in programming and it is now so easy that you can focus on business value, it is maybe time to dig into how to build more efficient programs. </p>
<blockquote>
<p>For a long time, the efficiency of a program was about lower cost and performance. But in 2021, we can add a third dimension - power efficiency 🌎. </p>
</blockquote>
<h2 id="heap-vs-stack">Heap vs Stack</h2>
<p>Java, Python, Javascript, Typescript, Go, Haskell, C# are managed programming languages. You don't need to think about memory allocation - does this variable <code>x</code> is allocated on the <em>heap</em> or on the <em>stack</em>? (<em>read more about  <a target="_blank" href="https://www.guru99.com/stack-vs-heap.html">Heap vs Stack</a></em>). On the other hand, programming languages like C, C++, and Rust forced you to think about how you want to memory allocate your variable <code>x</code>. </p>
<pre><code class="lang-python"><span class="hljs-comment"># Python - Stack x memory allocation</span>
x = <span class="hljs-string">"hello world"</span>
</code></pre>
<pre><code class="lang-rust"><span class="hljs-comment">// Rust - Stack x memory allocation</span>
<span class="hljs-keyword">let</span> x: &amp;<span class="hljs-built_in">str</span> = <span class="hljs-string">"hello world"</span>;
</code></pre>
<p>Those two var assignations look similar, right? They are! They are allocated on the Stack. The difference is that with Rust, we have more fine-grained control on the memory allocation. For instance, to allocate "hello world" on the Heap:</p>
<pre><code class="lang-rust"><span class="hljs-comment">// Rust - Heap x memory allocation</span>
<span class="hljs-keyword">let</span> x: <span class="hljs-built_in">String</span> = <span class="hljs-built_in">String</span>::from(<span class="hljs-string">"hello world"</span>);
</code></pre>
<p>Heap allocation is not explicitly possible with Python - The interpreter manages it for you.</p>
<p>To summarize: Stack is used for static memory allocation and Heap for dynamic memory allocation, both stored in the computer's RAM. Variables allocated on the stack are stored directly to the memory, and access to this memory is very fast. The Heap memory allocation is slower than the Stack memory allocation.</p>
<h2 id="reference-vs-value">Reference vs Value</h2>
<p>In Python, you don't even need to think about whether your function variables are passed by reference or value.</p>
<pre><code class="lang-python"><span class="hljs-comment"># declare a function "sum"</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">sum</span>(<span class="hljs-params">a, b</span>):</span>
  <span class="hljs-keyword">return</span> a + b

sum(<span class="hljs-number">2</span>, <span class="hljs-number">1</span>) <span class="hljs-comment"># the result is 3</span>
</code></pre>
<p>In this situation, values 2 and 1 are <strong>passed</strong> to the function <code>sum</code> <strong>by value</strong>.</p>
<pre><code class="lang-python"><span class="hljs-comment"># declare a function "sum" accepting a list object</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">sum</span>(<span class="hljs-params">elements</span>):</span>
  accumulator = <span class="hljs-number">0</span>
  <span class="hljs-keyword">for</span> e <span class="hljs-keyword">in</span> elements:
    accumulator += e

sum([<span class="hljs-number">2</span>, <span class="hljs-number">1</span>]) <span class="hljs-comment"># the result is 3</span>
</code></pre>
<p>And in this situation, the list with values 2 and 1 inside is <strong>passed</strong> to the function <code>sum</code> <strong>by reference</strong>. 🙄</p>
<blockquote>
<p>It is not exactly true. In Python, "object references are passed by value" and not by reference. But I will not go into details here.</p>
</blockquote>
<p>In Rust, you have to be specific if you want to pass a variable by reference or value.</p>
<pre><code class="lang-rust"><span class="hljs-comment">// pass by value</span>
<span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">sum</span></span>(a: <span class="hljs-built_in">u16</span>, b: <span class="hljs-built_in">u16</span>) -&gt; <span class="hljs-built_in">u16</span> {
  a + b
}

sum(<span class="hljs-number">2</span>, <span class="hljs-number">1</span>) <span class="hljs-comment">// the result is 3</span>
</code></pre>
<p>Values 2 and 1 are <strong>passed</strong> to the function <strong>by value</strong>. To pass by reference, you have to use <code>&amp;</code> explicitly.</p>
<pre><code class="lang-rust"><span class="hljs-comment">// pass by reference</span>
<span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">sum</span></span>(elements: &amp;<span class="hljs-built_in">Vec</span>&lt;<span class="hljs-built_in">u16</span>&gt;) -&gt; <span class="hljs-built_in">u16</span> {
  <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut</span> accumulator = <span class="hljs-number">0</span>;
  <span class="hljs-keyword">for</span> e <span class="hljs-keyword">in</span> elements {
    accumulator += e
  }

  accumulator
}

<span class="hljs-keyword">let</span> values = <span class="hljs-built_in">vec!</span>[<span class="hljs-number">2</span>, <span class="hljs-number">1</span>];
sum(&amp;values) <span class="hljs-comment">// the result is 3</span>
</code></pre>
<p>We pass a list of values by reference to the function <code>sum</code>. And we can do the same by passing the value of the list by removing <code>&amp;</code></p>
<pre><code class="lang-rust"><span class="hljs-comment">// move elements and consume them</span>
<span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">sum</span></span>(elements: <span class="hljs-built_in">Vec</span>&lt;<span class="hljs-built_in">u16</span>&gt;) -&gt; <span class="hljs-built_in">u16</span> {
  <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut</span> accumulator = <span class="hljs-number">0</span>;
  <span class="hljs-keyword">for</span> e <span class="hljs-keyword">in</span> elements {
    accumulator += e
  }

  accumulator
}

<span class="hljs-keyword">let</span> values = <span class="hljs-built_in">vec!</span>[<span class="hljs-number">2</span>, <span class="hljs-number">1</span>];
sum(values) <span class="hljs-comment">// the result is 3</span>
</code></pre>
<p>The difference is that Rust will consume the list and will remove it from memory. This is a specific behavior of Rust (read  <a target="_blank" href="https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html">ownership</a> ).</p>
<p>Passing variable by reference or value look anecdotal, but they are not when you need to build highly performant system like databases, embedded devices, and many others.</p>
<h1 id="build-safer-programs">Build safer programs</h1>
<p>As a programmer, when you start to build concurrent programs, you don't really realize how hard it is to write safe concurrent code. This is so abstracted and easy to write unsafe code that we all fall into the trap at least once, and even when we are more experienced. Let me show one unsafe Golang code that I saw one time from an experienced developer:</p>
<pre><code class="lang-go"><span class="hljs-comment">// golang example</span>
m := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">string</span>)

<span class="hljs-keyword">go</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(m <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">string</span>)</span></span> {
  m[<span class="hljs-string">"gender"</span>] = <span class="hljs-string">"male"</span>
}(m)

<span class="hljs-keyword">go</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(m <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">string</span>)</span></span> {
  m[<span class="hljs-string">"gender"</span>] = <span class="hljs-string">"female"</span>
}(m)

fmt.Println(m) <span class="hljs-comment">// m["gender"] is male or female?</span>
</code></pre>
<p><em>this is not the exact code, but the idea of concurrently modifying a hashmap was the same</em></p>
<p>So, the value of <code>m["gender"]</code> is <code>male</code> or <code>female</code>? 🤔 </p>
<p>We can't know. This code is not deterministic due to concurrent writes. If you run this code multiple times, you will sometimes have <code>male</code>, sometimes <code>female</code>, and even sometimes <code>fatal concurrent write errors</code> 😨 To concurrently edit the hashmap <code>m</code> you have to make it <em>thread safe</em>. This kind of error happens all the time, even to experienced developers in more complex situations. This is where Rust helps developers to prevent this kind of mistake. Here is the equivalent in Rust:</p>
<pre><code class="lang-rust"><span class="hljs-keyword">let</span> <span class="hljs-keyword">mut</span> m: HashMap&lt;&amp;<span class="hljs-built_in">str</span>, &amp;<span class="hljs-built_in">str</span>&gt; = HashMap::new();

thread::spawn(<span class="hljs-keyword">move</span> || {
  m[<span class="hljs-string">"gender"</span>] = <span class="hljs-string">"male"</span>;
});

thread::spawn(<span class="hljs-keyword">move</span> || {
  m[<span class="hljs-string">"gender"</span>] = <span class="hljs-string">"female"</span>;
});

<span class="hljs-built_in">println!</span>(<span class="hljs-string">"{:?}"</span>, m);
</code></pre>
<p>And the compiler prevents you from doing nasty stuff.</p>
<pre><code class="lang-bash">error[E0382]: use of moved value: `m`
  --&gt; src/main.rs:11:19
   |
5  |     <span class="hljs-built_in">let</span> mut m: HashMap&lt;&amp;str, &amp;str&gt; = HashMap::new();
   |         ----- move occurs because `m` has <span class="hljs-built_in">type</span> `HashMap&lt;&amp;str, &amp;str&gt;`, <span class="hljs-built_in">which</span> does not implement the `Copy` trait
6  |     
7  |     thread::spawn(move || {
   |                   ------- value moved into closure here
8  |        m[<span class="hljs-string">"gender"</span>] = <span class="hljs-string">"male"</span>;
   |        - variable moved due to use <span class="hljs-keyword">in</span> closure
...
11 |     thread::spawn(move || {
   |                   ^^^^^^^ value used here after move
12 |        m[<span class="hljs-string">"gender"</span>] = <span class="hljs-string">"female"</span>;
   |        - use occurs due to use <span class="hljs-keyword">in</span> closure
</code></pre>
<p>Rust compiler is super smart, it prevents you from doing race condition, and there is no way to compile this kind of code because it is simply wrong. That's why so many developers said that <a target="_blank" href="https://vorner.github.io/difficult.html">Rust is frustrating</a>. The Rust compiler is just honest with you and tells you the truth about your code. You were probably writing wrong code for long time, and you didn't know until now. I know, it's hard to change habits, and that's why in this kind of situation Rust is your best friend. It will always tell you the truth, even if it is not pleasant :)</p>
<p>A thread-safe code in Rust looks like this (don't use it in production - using <code>.unwrap()</code> here can block threads):</p>
<pre><code class="lang-rust"><span class="hljs-keyword">let</span> <span class="hljs-keyword">mut</span> m: Arc&lt;Mutex&lt;HashMap&lt;&amp;<span class="hljs-built_in">str</span>, &amp;<span class="hljs-built_in">str</span>&gt;&gt;&gt; = Arc::new(Mutex::new(HashMap::new()));

thread::spawn(<span class="hljs-keyword">move</span> || {
  m.lock().unwrap()[<span class="hljs-string">"gender"</span>] = <span class="hljs-string">"male"</span>;
});

thread::spawn(<span class="hljs-keyword">move</span> || {
  m.lock().unwrap()[<span class="hljs-string">"gender"</span>] = <span class="hljs-string">"female"</span>;
});

<span class="hljs-built_in">println!</span>(<span class="hljs-string">"{:?}"</span>, m);
</code></pre>
<h1 id="conclusion">Conclusion</h1>
<p>I hope you liked this article, and it gives you the appetite to try out Rust. If you have no idea how to start learning it, I would recommend reading <a target="_blank" href="https://doc.rust-lang.org/book/">the official free ebook</a>. Then, trying to reimplement some good old academic (or not) algorithms and data structures in Rust. If you want to put your hands into dirty stuff, I can recommend contributing to my project  <a target="_blank" href="https://github.com/Qovery/engine">Qovery Engine</a>  and  <a target="_blank" href="https://github.com/Qovery/redisless">RedisLess</a>  as well. </p>
<p>Here is a shortlist of Rust projects that I recommend to read:</p>
<ul>
<li><a target="_blank" href="https://github.com/meilisearch/MeiliSearch">Meilisearch</a> : Algolia and Elasticsearch search engine alternative.</li>
<li><a target="_blank" href="https://github.com/valeriansaliou/sonic">Sonic</a> : Lightweight Elasticsearch alternative.</li>
<li><a target="_blank" href="https://github.com/spacejam/sled">Sled</a> : Storage engine written in Rust - alternative to RocksDB.</li>
<li><a target="_blank" href="https://github.com/alex-dukhno/isomorphicdb">IsomorphicDB</a> : PostgreSQL clone - it is a good experimental project written in Rust.</li>
<li><a target="_blank" href="https://github.com/tikv/raft-rs">Raft-rs</a> : Raft consensus protocol implemented in Rust by PingCap.</li>
<li><a target="_blank" href="https://github.com/Qovery/redisless">RedisLess</a>: RedisLess is a fast, lightweight, embedded, and scalable in-memory Key/Value store library compatible with the Redis API. </li>
<li><a target="_blank" href="https://github.com/Qovery/engine">Qovery Engine</a>:  Qovery Engine is an open-source abstraction layer library that turns easy apps deployment on AWS, GCP, Azure, and other Cloud providers in just a few minutes.</li>
</ul>
<p>==========</p>
<p><a target="_blank" href="https://jobs.qovery.com">I am hiring Rust developers</a> for my wonderful <a target="_blank" href="https://www.qovery.com">company</a>.</p>
]]></content:encoded></item><item><title><![CDATA[RedisLess - Blazingly fast Serverless Redis]]></title><description><![CDATA[THIS PROJECT IS NOT PRODUCTION READY YET!!

Imagine a world where your database is nothing more than a lib in your app 🥰. 
Imagine a world where using Redis is as simple as npm install redisless, and that's it!
If you dream of this world (as I do), ...]]></description><link>https://www.heapstack.sh/redisless-blazingly-fast-serverless-redis</link><guid isPermaLink="true">https://www.heapstack.sh/redisless-blazingly-fast-serverless-redis</guid><category><![CDATA[Redis]]></category><category><![CDATA[serverless]]></category><category><![CDATA[Cloud]]></category><category><![CDATA[Rust]]></category><category><![CDATA[Python]]></category><dc:creator><![CDATA[Romaric Philogène]]></dc:creator><pubDate>Wed, 28 Apr 2021 06:13:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1619590333509/c4obSGPCZ.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<hr />
<p><strong>THIS PROJECT IS NOT PRODUCTION READY YET!!</strong></p>
<hr />
<p>Imagine a world where your database is nothing more than a lib in your app 🥰. </p>
<p>Imagine a world where using Redis is as simple as <code>npm install redisless</code>, and that's it!</p>
<p>If you dream of this world (as I do), then you will love RedisLess - and hopefully, be part of this journey 🥳.</p>
<h1 id="what-is-redisless">What is RedisLess</h1>
<p><strong><a target="_blank" href="https://github.com/Qovery/RedisLess">RedisLess</a> is a fast, lightweight, embedded, and scalable in-memory Key/Value store library compatible with the Redis API.</strong></p>
<blockquote>
<p>The project is still early, so don't take any of those words for granted at the moment. </p>
</blockquote>
<p>RedisLess is written in Rust and export functions through FFI (Foreign Function Interface), making it usable from any language. I've started to write clients for NodeJS and Python. </p>
<h1 id="how-to-use-redisless">How to use RedisLess</h1>
<p>To use RedisLess, you only need to:</p>
<ol>
<li>Install the RedisLess library for your favorite language.</li>
<li>Connect your favorite Redis client to <code>redis://localhost:16379</code>.</li>
<li>You don't need to change your code - RedisLess is Redis API compatible.</li>
</ol>
<p>Under the hood, the RedisLess library starts a local Redis API compatible instance on port <code>16739</code> (you can change the port).</p>
<h2 id="python-usage-example">Python usage example</h2>
<p>Here a simple example in Python</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> redisless <span class="hljs-keyword">import</span> RedisLess
<span class="hljs-keyword">import</span> redis

redisless = RedisLess()

<span class="hljs-comment"># start RedisLess embedded instance</span>
redisless.start()

<span class="hljs-comment"># Connect to RedisLess on localhost:16379</span>
redis = redis.Redis(host=<span class="hljs-string">'localhost'</span>, port=<span class="hljs-number">16379</span>, db=<span class="hljs-number">0</span>)

redis.set(<span class="hljs-string">'foo'</span>, <span class="hljs-string">'bar'</span>)
redis.get(<span class="hljs-string">'foo'</span>)  <span class="hljs-comment"># return bar </span>

<span class="hljs-comment"># stop RedisLess embedded instance</span>
redisless.stop()
</code></pre>
<p>As you can see, we are using the official Python Redis client to connect to RedisLess. Nothing else. Meaning, if you are already using Redis in your code, you can use RedisLess without changing a single line of code. Is it magic? No, it is not. Let me explain how it works.</p>
<h1 id="supported-languages">Supported languages</h1>
<ul>
<li>[wip] Python</li>
<li>[wip] NodeJS</li>
<li>[-] Golang</li>
<li>[-] Java / Kotlin</li>
</ul>
<p>Supporting a new language can be done in 5 minutes. Look at <a target="_blank" href="https://github.com/Qovery/RedisLess/tree/main/clients/python">Python</a> and <a target="_blank" href="https://github.com/Qovery/RedisLess/tree/main/clients/nodejs">NodeJS</a> clients implementation for inspiration.</p>
<h1 id="how-redisless-works">How RedisLess works</h1>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cty9r38cylsw6rqhc2iq.jpg" alt="RedisLess vs Redis Server" /></p>
<p>The main characteristic is that RedisLess runs inside your app, where Redis Server runs inside a dedicated service and instance. It is a considerable difference because RedisLess does not need any external dependency to work. The more you have apps running, the more your app is resilient to failure.</p>
<p>Here is a specs comparison table</p>
<table>
<thead>
<tr>
<td>Spec</td><td>RedisLess</td><td>Redis Server</td></tr>
</thead>
<tbody>
<tr>
<td>Redis API compatibility</td><td>partial</td><td>full</td></tr>
<tr>
<td>Serverless</td><td>yes</td><td>no</td></tr>
<tr>
<td>Consistency</td><td>strong</td><td>strong</td></tr>
<tr>
<td>Read performance</td><td>constant</td><td>constant</td></tr>
<tr>
<td>Write performance</td><td>constant</td><td>constant</td></tr>
<tr>
<td>Cluster consistency</td><td>eventually</td><td>eventually</td></tr>
<tr>
<td>Cluster read performance</td><td>constant</td><td>constant</td></tr>
<tr>
<td>Cluster write performance</td><td>slower</td><td>constant</td></tr>
<tr>
<td>Consensus protocol</td><td>Raft</td><td>RedisRaft</td></tr>
<tr>
<td>Disk persistence</td><td>no</td><td>yes</td></tr>
<tr>
<td>Support cloud-native environment</td><td>yes</td><td>no</td></tr>
</tbody>
</table>
<h2 id="features-highlight">Features highlight</h2>
<h3 id="redis-api">Redis API</h3>
<p>RedisLess is not 100% Redis API compatible. Meaning, some commands like <code>CLIENT TRACKING</code>, <code>AUTH</code>, and <code>ACL LOAD</code> are irrelevant. However, transactions are not available right now but will be in the future. It just takes time to implement features.</p>
<h3 id="built-for-the-cloud">Built for the Cloud</h3>
<p>Redis Server was built before the Cloud was a thing. If you want to use Redis Server properly, you have to set up an instance with local storage and do some fine-tuning to make it works properly for high and intensive usage. RedisLess does not need anything like this. No need to spend time managing servers. It works in memory within your app. It is much easier when your app runs in a Cloud-native environment (E.g. within a container / Kubernetes / function as a service) and needs to scale dynamically based on the workload. </p>
<h3 id="slower-cluster-write-performance">Slower Cluster write performance</h3>
<p>If you are familiar with distributed system, you probably know that it is impossible to have strong consistency, high availability, and high performance all at the same time. You have to choose. Redis Server Cluster lets you decide how you want to configure your cluster and then gives you a choice between performance and availability. With RedisLess, we make the choice of availability for writes and performance for reads with eventual consistency. It is not a definitive choice.</p>
<h1 id="contribution">Contribution</h1>
<blockquote>
<p>RedisLess is in its early days, but I am serious about building a solid library to help thousands of developers.</p>
</blockquote>
<p>It is never too soon to contribute and be part of a great project. If you are interested in contributing, join us on <a target="_blank" href="https://discord.qovery.com">Discord</a>. </p>
<h1 id="genesa-of-this-project">Genesa of this project</h1>
<p><strong>One year ago, I started a <a target="_blank" href="https://www.qovery.com">company</a> with <a target="_blank" href="https://twitter.com/deimosfr">Pierre Mavro</a></strong>. We wanted to make app deployment easy for any developer. Today, 2666 developers from more than 110 countries deploy their apps on AWS and Digital Ocean using our product. I saw firsthand how developers struggle during days (sometimes weeks 😨) to deploy their apps. But why is it so complicated? Deploying an app itself is not complex. But setting up all external dependencies to make it works is. What about configuring servers, databases, networks? Even with the Cloud, it is not so simple. That's why <a target="_blank" href="https://www.qovery.com/team">my team</a> and I wanted to go further than app deployment and <strong><a target="_blank" href="https://www.qovery.com/blog/the-easiest-way-to-deploy-your-database-the-future-of-qovery-week-7">build the future of database management</a></strong>. </p>
<h1 id="how-to-join-the-project">How to join the project</h1>
<p>If you are interested in contributing (even if you don't know yet how). Comment on this post and indicate:</p>
<ul>
<li>What languages do you use?</li>
<li>What is your experience: beginner, experienced, expert?</li>
<li>Do you have experience in contributing Open-Source projects?</li>
<li>A few words about you and why you are interested in RedisLess.</li>
</ul>
<hr />
<p>👉 Please support us with a <a target="_blank" href="https://github.com/Qovery/RedisLess">Github star</a> ⭐️.</p>
<hr />
<p>Thanks to @pjeziorowski for his contribution to this post. ❤️</p>
]]></content:encoded></item><item><title><![CDATA[Coding is addictive - thoughts of a dev CEO]]></title><description><![CDATA[I like to code! After a long day of calls, managing my teams, and making sure the business at Qovery moves in the right direction. I like spending 1-hour coding, even at 2 am 😄. It's quite addictive! For me, coding is art. It is the paintbrush that ...]]></description><link>https://www.heapstack.sh/coding-is-addictive-thoughts-of-a-dev-ceo</link><guid isPermaLink="true">https://www.heapstack.sh/coding-is-addictive-thoughts-of-a-dev-ceo</guid><category><![CDATA[lifestyle]]></category><category><![CDATA[programing]]></category><dc:creator><![CDATA[Romaric Philogène]]></dc:creator><pubDate>Sun, 28 Mar 2021 20:22:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1616962867509/SU0y9f8vr.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I like to code! After a long day of calls, managing my teams, and making sure the business at <a target="_blank" href="https://www.qovery.com">Qovery</a> moves in the right direction. I like spending 1-hour coding, even at 2 am 😄. It's quite addictive! For me, coding is art. It is the paintbrush that makes you able to express yourself with endless possibilities. </p>
<pre><code class="lang-rust"><span class="hljs-comment">/// I am Rust code -- https://github.com/Qovery/engine</span>
<span class="hljs-keyword">pub</span> <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">delete_stateless_service</span></span>&lt;T&gt;(
        target: &amp;DeploymentTarget, 
        service: &amp;T, 
        is_error: <span class="hljs-built_in">bool</span>
) -&gt; <span class="hljs-built_in">Result</span>&lt;(), EngineError&gt;
<span class="hljs-keyword">where</span>
    T: Service + Helm,
{
    <span class="hljs-keyword">let</span> (kubernetes, environment) = <span class="hljs-keyword">match</span> target {
        DeploymentTarget::ManagedServices(k, env) =&gt; (*k, *env),
        DeploymentTarget::SelfHosted(k, env) =&gt; (*k, *env),
    };

    <span class="hljs-keyword">let</span> helm_release_name = service.helm_release_name();

    <span class="hljs-keyword">if</span> is_error {
        <span class="hljs-keyword">let</span> _ = get_stateless_resource_information(kubernetes, environment, service.selector().as_str())?;
    }

    <span class="hljs-comment">// clean the resource</span>
    <span class="hljs-keyword">let</span> _ = do_stateless_service_cleanup(kubernetes, environment, helm_release_name.as_str())?;

    <span class="hljs-literal">Ok</span>(())
}
</code></pre>
<p><a target="_blank" href="https://github.com/Qovery/engine/blob/dev/src/cloud_provider/service.rs#L473">This is art</a> 😍 </p>
<p>I used to <a target="_blank" href="https://twitter.com/rophilogene/status/1355247124162744321">play piano</a>, <a target="_blank" href="https://www.youtube.com/watch?v=5_7kQjec4-A">produce electronic music</a>, and play lego when I was young. Coding is perfect for expressing your creativity and much more than that...</p>
<h2 id="coding-is-fun-not-dumb">Coding is fun, not dumb</h2>
<p>Absolutely, coding is fun. Do you know <a target="_blank" href="https://www.codingame.com/">CodinGame</a> and  <a target="_blank" href="https://www.codewars.com/">Codewars</a>? People like me are crazy enough to spend time doing coding exercises to improve their skills and their ability to resolve problems. I like new challenges and coding is perfect for that. What about coding in a new language a problem that you have solved 100 times in your day-to-day programming language? Did you hear about Object Oriented Programming or Functional Programming? They are two different ways of solving the same problems. It's like going back home from school but using a different path than usual. Your brain is a muscle, using it in a different manner helps to make it even stronger to solve a large variety of problems. This is so cool 🤯🤩</p>
<pre><code class="lang-python"><span class="hljs-comment"># iterative</span>
a = []
<span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> range(<span class="hljs-number">100</span>):
  a.append(x*<span class="hljs-number">2</span>)

<span class="hljs-comment"># comprehension list</span>
b = [x*<span class="hljs-number">2</span> <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> range(<span class="hljs-number">100</span>)]

<span class="hljs-comment"># functional</span>
c = list(map(<span class="hljs-keyword">lambda</span> x: x*<span class="hljs-number">2</span>, range(<span class="hljs-number">100</span>)))

<span class="hljs-comment"># a == b == c</span>
</code></pre>
<blockquote>
<p>3 different ways of doing the same operation in Python</p>
</blockquote>
<h2 id="coding-is-rewarding">Coding is rewarding</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1616961632593/TApdX7j65.jpeg" alt="brain teasers box" /></p>
<p>I love brain teasers. Those games where I spend minutes to hours to find out what's the solution for them is so enjoyable 😄. Coding is about finding the most optimal solution to a problem. At <a target="_blank" href="https://www.qovery.com">Qovery</a> (my company), our current main challenge is to turn app deployment seamless for developers on AWS, GCP, Azure... To achieve that, we need to solve tons of smaller problems. This is where I love my job 🍿Divide to conquer is rule number one.</p>
<h2 id="coding-is-like-superpowers">Coding is like superpowers</h2>
<p>In a digital world, being able to understand and talk the language of computers is divine. Even <a target="_blank" href="https://github.com/muhammadh-s/order-pizza-api">ordering your pizza</a> is possible through <a target="_blank" href="https://en.wikipedia.org/wiki/Web_API">web API</a>.</p>
<pre><code class="lang-bash">curl 
  -H <span class="hljs-string">"Content-Type: application/json"</span> 
  -H <span class="hljs-string">"Authorization: Bearer &lt;JWT&gt;"</span> 
  -X POST 
  -d  
 <span class="hljs-string">'{
    "Flavor": "ABC", 
    "Crust": "XYZ",
    "Size": "XL", 
    "Table_No": 9
  }'</span> 
  https://order-pizza-api.herokuapp.com/api/orders
</code></pre>
<p>🍕</p>
<h2 id="coding-makes-you-better-ceo-in-2021">Coding makes you better CEO in 2021</h2>
<pre><code class="lang-python"><span class="hljs-comment"># I am Python code</span>
prospects = [p <span class="hljs-keyword">for</span> p <span class="hljs-keyword">in</span> linkedin_profiles <span class="hljs-keyword">if</span> profile.good_prospect()]
<span class="hljs-keyword">for</span> protest <span class="hljs-keyword">in</span> prospects:
  <span class="hljs-comment"># this is how we make money right? :D</span>
  prospect.sell_product()
</code></pre>
<p>It has never been so easy to launch a company in 2021. With almost no fund, you can start to build the company of your dream online. The only problem is if you have no coding skills, you will no go very far without asking for help from someone $$$ (yes, I know there are plenty of no-code tools -- but at some point, you'll need to code something -- if you have a CTO, you're safe then :)). </p>
<p>For instance, last week, I worked on scraping the data from a few sources to better know my users. And I didn't need to disturb my team to do so. </p>
<p>And the week before, I created our <a target="_blank" href="https://www.qovery.com/community-call">Community Call</a> page. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1616954791234/XgSrQMbgl.png" alt="Qovery Community Call page" /></p>
<p>You are never better served than by yourself. This is all about freedom. </p>
<p>I am a creative, maker, and entrepreneur. I love to be free, and not relying on anyone to achieve what you have in mind is gold! Happy coding 👋</p>
<p>Reads:</p>
<ul>
<li><a target="_blank" href="https://steemit.com/programming/@noble-noah/programming-addiction">Programming addiction</a></li>
<li><a target="_blank" href="https://www.khanacademy.org/science/in-in-class-12-biology-india/xc09ed98f7a9e671b:in-in-human-health-and-disease/xc09ed98f7a9e671b:in-in-addiction-and-dependence/v/reward-pathway-in-the-brain">Reward pathway in the brain (video)</a></li>
</ul>
<p>And you? Are you a coding addict too?</p>
<p>--
Pssst: <a target="_blank" href="https://jobs.qovery.com">I am hiring</a> 👨‍💻</p>
<p>Romaric.</p>
]]></content:encoded></item></channel></rss>