<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Ci-Cd on WebDevStation</title>
    <link>https://webdevstation.com/tags/ci-cd/</link>
    <description>1 article tagged Ci-Cd — tutorials, code examples and notes from building real systems, newest first.</description>
    <generator>Hugo</generator>
    <language>en</language>
    <managingEditor>Alex</managingEditor>
    <webMaster>Alex</webMaster>
    <copyright>© 2026 WebDevStation</copyright>
    <lastBuildDate>Fri, 12 Feb 2021 18:56:46 +0000</lastBuildDate>
    <atom:link href="https://webdevstation.com/tags/ci-cd/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>An Easy Way to Load Test Your Web Apps</title>
      <link>https://webdevstation.com/posts/an-easy-way-to-loadtest-your-web-apps/</link>
      <pubDate>Fri, 12 Feb 2021 18:56:46 +0000</pubDate>
      <author>Alex</author>
      <guid isPermaLink="true">https://webdevstation.com/posts/an-easy-way-to-loadtest-your-web-apps/</guid>
      <description>Learn how to implement effective load testing for your web applications using the k6 tool and automate performance testing in your GitLab CI/CD pipeline.</description>
      <content:encoded><![CDATA[<p>This time, I want to share my positive experience of load testing of one of our web services, by using <a href="https://k6.io/">K6</a> tool.
Moreover, we will see how easily we can integrate this into the GitLab CI pipeline.</p>
<p>When you develop web applications, it&rsquo;s crucial to have a testing strategy. Nobody argues about the importance of unit,
functional, and integration testing. Nevertheless, very often developers forget to test how their application works under high load.
Even, when we have a &ldquo;green light&rdquo; from all our testing stages, including manual testing, better to not release it to production, until you load test it.
Otherwise, nobody can guarantee, that application will work properly when 50 users will use it simultaneously.</p>
<p>In this article I&rsquo;m going to load test our web application from the <a href="https://webdevstation.com/posts/how-to-show-flash-messages-in-go-echo/">previous article</a>.</p>
<p>For that, we are going to use a K6 tool, written in Go, and uses JavaScript for scripting.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>k6 is a developer-centric, free and open-source load testing tool built for making performance testing a productive and enjoyable experience.
</span></span></code></pre></div><p>Let&rsquo;s install this tool:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>brew install k6
</span></span></code></pre></div><p>If you have different from the macOS operating system, please read about others ways to install <a href="https://k6.io/docs/getting-started/installation">here</a>.</p>
<p>Next, we create a <code>loadtests</code> folder in the root of our project and inside we add a <code>test.js</code> file, where we are going to write our load tests scenarios:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">import</span> { <span style="color:#a6e22e">sleep</span> } <span style="color:#a6e22e">from</span> <span style="color:#e6db74">&#39;k6&#39;</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">import</span> <span style="color:#a6e22e">http</span> <span style="color:#a6e22e">from</span> <span style="color:#e6db74">&#39;k6/http&#39;</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">import</span> { <span style="color:#a6e22e">check</span> } <span style="color:#a6e22e">from</span> <span style="color:#e6db74">&#39;k6&#39;</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">import</span> { <span style="color:#a6e22e">Rate</span> } <span style="color:#a6e22e">from</span> <span style="color:#e6db74">&#39;k6/metrics&#39;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">export</span> <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">errorRate</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Rate</span>(<span style="color:#e6db74">&#39;errors&#39;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">export</span> <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">options</span> <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Here we define our scenarios.
</span></span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">scenarios</span><span style="color:#f92672">:</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">sign_in_page_test</span><span style="color:#f92672">:</span> {
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">executor</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;constant-vus&#39;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">duration</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;1m&#39;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">vus</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">100</span>, <span style="color:#75715e">// amount of the virtual users
</span></span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">tags</span><span style="color:#f92672">:</span> { <span style="color:#a6e22e">test_type</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;signInPage&#39;</span> },
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">exec</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;signInPage&#39;</span>,
</span></span><span style="display:flex;"><span>        },
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// List of thresholds.
</span></span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">thresholds</span><span style="color:#f92672">:</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">http_req_duration</span><span style="color:#f92672">:</span> [<span style="color:#e6db74">&#39;avg&lt;500&#39;</span>], <span style="color:#75715e">// avg response times must be below 0.5s
</span></span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">errors</span><span style="color:#f92672">:</span> [<span style="color:#e6db74">&#39;rate&lt;0.1&#39;</span>], <span style="color:#75715e">// &lt;10% errors
</span></span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>};
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">export</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">signInPage</span>() {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">res</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">http</span>.<span style="color:#a6e22e">get</span>(<span style="color:#a6e22e">getDomain</span>() <span style="color:#f92672">+</span> <span style="color:#e6db74">&#39;/user/signin&#39;</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Here we check the response status.
</span></span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">result</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">check</span>(<span style="color:#a6e22e">res</span>, {
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#39;status is 200&#39;</span><span style="color:#f92672">:</span> (<span style="color:#a6e22e">r</span>) =&gt; <span style="color:#a6e22e">r</span>.<span style="color:#a6e22e">status</span> <span style="color:#f92672">==</span> <span style="color:#ae81ff">200</span>,
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// If it&#39;s different from 200, add info to the errorRate.
</span></span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">errorRate</span>.<span style="color:#a6e22e">add</span>(<span style="color:#f92672">!</span><span style="color:#a6e22e">result</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">sleep</span>(<span style="color:#ae81ff">3</span>)
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Gets the domain from the environment variables.
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">getDomain</span>() {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">__ENV</span>.<span style="color:#a6e22e">DOMAIN</span>;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Above, we have declared a scenario to load test <code>/user/signin</code> page with 100 virtual users who continuously accessing our page in parallel.</p>
<p>To run this load test, we need to execute this command in the terminal:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>k6 run --env DOMAIN<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;http://localhost:8777&#34;</span> ./loadtests/test.js
</span></span></code></pre></div><p>After some time we will see this results output:
<img src="/images/0221/k6.png" alt="k6 terminal output listing checks, request duration percentiles and the passing thresholds for the load test" title="k6 load test results in the terminal"></p>
<p>As you could notice, all our defined thresholds were satisfied. So far so good!</p>
<p>Now, let&rsquo;s see how we can integrate load testing to the Gitlab CI pipeline. Fortunately, it&rsquo;s easy to do :)</p>
<p>Inside <code>.gitlab-ci.yml</code> we need to add this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">stages</span>:
</span></span><span style="display:flex;"><span>  - <span style="color:#ae81ff">loadtest</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">loadtesting</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">stage</span>: <span style="color:#ae81ff">loadtest</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">image</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">loadimpact/k6:latest</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">entrypoint</span>: [ <span style="color:#e6db74">&#39;&#39;</span> ]
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">variables</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">DOMAIN</span>: <span style="color:#e6db74">&#39;[your-testing-domain-here]&#39;</span>  
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">script</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">echo &#34;executing K6 load tests in k6 container...&#34;</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">k6 run --env DOMAIN=${DOMAIN} ./loadtests/test.js</span>
</span></span></code></pre></div><p>That was it! I&rsquo;ve described just an idea how you can easily integrate the load testing in your development routine.
In the real-world situations you might create more complex load testing scenarios, which will help you find weak points of your application and prevent unexpected downtimes.</p>
<p>I wish you happy coding and no pagerduty calls during the night!😉</p>
<p>Once you can measure, you have something to optimise against. Two places I usually look first: <a href="/posts/early-hints-in-go-or-the-way-of-how-to-improve-perforamnce-of-web-page/">103 Early Hints in Go</a> for front-end latency, and <a href="/posts/ristretto-the-most-performant-concurrent-cache-library-for-go/">Ristretto caching</a> for the expensive calls behind it. It is also the right tool to prove your <a href="/posts/graceful-shutdown-in-go-web-services/">graceful shutdown</a> really does keep errors at zero during a deploy.</p>]]></content:encoded>
      <category>DevOps</category>
      <category>Testing</category>
    </item>
  </channel>
</rss>
