<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Željko Šević</title>
    <description>The latest articles on DEV Community by Željko Šević (@zsevic).</description>
    <link>https://dev.to/zsevic</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F329310%2F1134d19a-755a-427e-b2f4-fb9d4166b783.png</url>
      <title>DEV Community: Željko Šević</title>
      <link>https://dev.to/zsevic</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zsevic"/>
    <language>en</language>
    <item>
      <title>Infrastructure as Code (IaC) with Terraform (AWS EC2 Example)</title>
      <dc:creator>Željko Šević</dc:creator>
      <pubDate>Tue, 28 Apr 2026 10:02:38 +0000</pubDate>
      <link>https://dev.to/zsevic/infrastructure-as-code-iac-with-terraform-aws-ec2-example-3db0</link>
      <guid>https://dev.to/zsevic/infrastructure-as-code-iac-with-terraform-aws-ec2-example-3db0</guid>
      <description>&lt;p&gt;Infrastructure as Code (IaC) is a DevOps approach where infrastructure is defined and managed using code instead of manual setup. This makes environments reproducible, version-controlled, and easy to scale.&lt;/p&gt;

&lt;p&gt;In this guide, you'll provision an AWS EC2 instance using Terraform.&lt;/p&gt;

&lt;h3&gt;
  
  
  Requirements
&lt;/h3&gt;

&lt;p&gt;Before starting, install:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Terraform
&lt;/li&gt;
&lt;li&gt;AWS CLI
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  AWS Credentials Setup
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to IAM → Security credentials in AWS
&lt;/li&gt;
&lt;li&gt;Create access keys
&lt;/li&gt;
&lt;li&gt;Configure locally:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws configure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This stores credentials in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;~/.aws/credentials&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;~/.aws/config&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Project Structure
&lt;/h3&gt;

&lt;p&gt;A simple Terraform setup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── main.tf
├── variables.tf
├── terraform.tfvars
├── outputs.tf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Provider Configuration
&lt;/h3&gt;

&lt;p&gt;Define your cloud provider in &lt;code&gt;main.tf&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"aws"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;profile&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"default"&lt;/span&gt;
  &lt;span class="nx"&gt;region&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"eu-north-1"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Variables
&lt;/h3&gt;

&lt;p&gt;Define reusable variables in &lt;code&gt;variables.tf&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"instance_name"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Name tag for EC2 instance"&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"MyNewInstance"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"ec2_instance_type"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"EC2 instance type"&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"t3.micro"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set values in &lt;code&gt;terraform.tfvars&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;instance_name&lt;/span&gt;      &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"MyEC2Name"&lt;/span&gt;
&lt;span class="nx"&gt;ec2_instance_type&lt;/span&gt;  &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"t3.micro"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  EC2 Instance Configuration
&lt;/h3&gt;

&lt;p&gt;Add the resource in &lt;code&gt;main.tf&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_instance"&lt;/span&gt; &lt;span class="s2"&gt;"app_server"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;ami&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ami-077d1b9f9a1902bbc"&lt;/span&gt;
  &lt;span class="nx"&gt;instance_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ec2_instance_type&lt;/span&gt;

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instance_name&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can find AMI IDs in EC2 → Images → AMI Catalog.&lt;/p&gt;

&lt;h3&gt;
  
  
  Outputs
&lt;/h3&gt;

&lt;p&gt;Expose useful data in &lt;code&gt;outputs.tf&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"instance_id"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"EC2 instance ID"&lt;/span&gt;
  &lt;span class="nx"&gt;value&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;app_server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"instance_public_ip"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Public IP address"&lt;/span&gt;
  &lt;span class="nx"&gt;value&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;app_server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;public_ip&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Terraform Workflow
&lt;/h3&gt;

&lt;p&gt;Initialize the project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;terraform init&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Preview changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;terraform plan&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Apply changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;terraform apply&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Destroy infrastructure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;terraform destroy&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Important Notes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;State file&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Terraform stores infrastructure state in &lt;code&gt;terraform.tfstate&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Do not commit this file to Git.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remote state (recommended)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For teams, store state in S3 with locking via DynamoDB.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Idempotency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Running &lt;code&gt;apply&lt;/code&gt; multiple times won’t recreate resources unnecessarily.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Version control&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Treat Terraform code like application code.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>terraform</category>
      <category>aws</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>Load and stress testing with Artillery</title>
      <dc:creator>Željko Šević</dc:creator>
      <pubDate>Sat, 25 Apr 2026 13:52:36 +0000</pubDate>
      <link>https://dev.to/zsevic/load-and-stress-testing-with-artillery-1nfi</link>
      <guid>https://dev.to/zsevic/load-and-stress-testing-with-artillery-1nfi</guid>
      <description>&lt;p&gt;&lt;a href="https://www.artillery.io/" rel="noopener noreferrer"&gt;Artillery&lt;/a&gt; is a performance testing tool. This post explains types of performance testing and dives into &lt;code&gt;Artillery&lt;/code&gt; usage, from configuration to running tests and checking results.&lt;/p&gt;

&lt;h3&gt;
  
  
  Load and stress testing
&lt;/h3&gt;

&lt;p&gt;Load and stress testing are two types of performance testing used to evaluate how well a system performs under various conditions.&lt;/p&gt;

&lt;p&gt;Load testing determines how the system performs under expected user loads. The purpose is to identify performance bottlenecks.&lt;/p&gt;

&lt;p&gt;Stress testing assesses how the system performs when loads are heavier than usual. The purpose is to find the limit at which the system fails and to observe how it recovers from such failures.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.artillery.io/" rel="noopener noreferrer"&gt;Artillery&lt;/a&gt; available via &lt;code&gt;npx&lt;/code&gt; (or installed in project dev dependencies)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;YAML config file that defines target, phases and scenarios&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Optional CSV payload file for dynamic test data&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Configuration
&lt;/h3&gt;

&lt;p&gt;Artillery test configuration is defined in a YAML file (for example, &lt;code&gt;.artillery/main.yml&lt;/code&gt;). It typically contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;target&lt;/code&gt;: base URL of the app (&lt;code&gt;http://localhost:3000&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;phases&lt;/code&gt;: load shape over time&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;payload&lt;/code&gt;: CSV file for dynamic values&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;scenarios&lt;/code&gt;: user flows and weights&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For realistic load tests, configure these parts intentionally:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Define phases for warm-up, ramp-up, and sustained load.&lt;/li&gt;
&lt;li&gt;Use a CSV payload when requests require dynamic values (IDs, emails, tokens, and similar).&lt;/li&gt;
&lt;li&gt;Use weighted scenarios to simulate realistic traffic distribution across endpoints.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;http://localhost:3000'&lt;/span&gt;
  &lt;span class="na"&gt;phases&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;
      &lt;span class="na"&gt;arrivalRate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Warm up&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;
      &lt;span class="na"&gt;arrivalRate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
      &lt;span class="na"&gt;rampTo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Ramp up load&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;
      &lt;span class="na"&gt;arrivalRate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Sustained load&lt;/span&gt;
  &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;dynamic_data.csv'&lt;/span&gt;
    &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;CustomerId'&lt;/span&gt;
&lt;span class="na"&gt;scenarios&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Get&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;customer's&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;tracks"&lt;/span&gt;
    &lt;span class="na"&gt;flow&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/customers/{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;CustomerId&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}/tracks'&lt;/span&gt;
    &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Get&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;customers&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;pdf'&lt;/span&gt;
    &lt;span class="na"&gt;flow&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/customers/pdf'&lt;/span&gt;
    &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Scenario flow and dynamic data
&lt;/h3&gt;

&lt;p&gt;Scenarios define user actions during the test.&lt;/p&gt;

&lt;p&gt;In the example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;80% of users run &lt;code&gt;Get customer's tracks&lt;/code&gt; (&lt;code&gt;weight: 4&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;20% of users run &lt;code&gt;Get customers pdf&lt;/code&gt; (&lt;code&gt;weight: 1&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dynamic data is loaded from &lt;code&gt;.artillery/dynamic_data.csv&lt;/code&gt;, and &lt;code&gt;{{ CustomerId }}&lt;/code&gt; is injected into request URLs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running tests
&lt;/h3&gt;

&lt;p&gt;Load tests can be executed through an npm script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"test:load"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"artillery run ./.artillery/main.yml"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the test with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run &lt;span class="nb"&gt;test&lt;/span&gt;:load
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also run Artillery directly with &lt;code&gt;npx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx artillery run ./.artillery/main.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Test report
&lt;/h3&gt;

&lt;p&gt;By default, Artillery prints a terminal summary with key metrics such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;failed virtual users and HTTP error/status-code distribution&lt;/li&gt;
&lt;li&gt;response-time percentiles (especially p95 and p99)&lt;/li&gt;
&lt;li&gt;median response time (p50)&lt;/li&gt;
&lt;li&gt;requests per second and total request volume&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To save raw results and generate an HTML report:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx artillery run &lt;span class="nt"&gt;--output&lt;/span&gt; report.json ./.artillery/main.yml
npx artillery report report.json &lt;span class="nt"&gt;--output&lt;/span&gt; report.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This generates a shareable HTML report with latency percentiles, throughput and error trends.&lt;/p&gt;

&lt;p&gt;When reading Artillery reports, focus on these metrics first:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Error rate&lt;/strong&gt; (&lt;code&gt;vusers.failed&lt;/code&gt;, non-2xx/3xx codes): the most important health signal. Even small error percentages can indicate instability under load.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tail latency&lt;/strong&gt; (&lt;code&gt;p95&lt;/code&gt;, &lt;code&gt;p99&lt;/code&gt;): shows worst-case user experience. Systems can have a good median but still feel slow for a significant group of users.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Median latency&lt;/strong&gt; (&lt;code&gt;p50&lt;/code&gt;/&lt;code&gt;median&lt;/code&gt;): useful for baseline responsiveness, but should always be evaluated together with p95/p99.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Throughput&lt;/strong&gt; (&lt;code&gt;http.requests&lt;/code&gt;, requests/sec): confirms how much traffic the system handled during the test.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trend over time&lt;/strong&gt; (&lt;code&gt;intermediate&lt;/code&gt; snapshots): helps identify whether performance degrades during ramp-up or sustained load.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short: start with reliability (errors), then check latency percentiles (especially p95/p99), and finally validate throughput and time-based stability.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>artillery</category>
      <category>node</category>
    </item>
    <item>
      <title>HTTP timeout with Axios</title>
      <dc:creator>Željko Šević</dc:creator>
      <pubDate>Wed, 25 Sep 2024 23:29:23 +0000</pubDate>
      <link>https://dev.to/zsevic/http-timeout-with-axios-4kah</link>
      <guid>https://dev.to/zsevic/http-timeout-with-axios-4kah</guid>
      <description>&lt;p&gt;Setting up a timeout for HTTP requests can prevent the connection from hanging forever, waiting for the response. It can be set on the client side to improve user experience, and on the server side to improve inter-service communication.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;axios&lt;/code&gt; package provides a &lt;code&gt;timeout&lt;/code&gt; parameter for this functionality.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;HTTP_TIMEOUT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://www.google.com:81&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HTTP_TIMEOUT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Request timed out&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cause&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use this snippet also to simulate aborted requests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Course
&lt;/h3&gt;

&lt;p&gt;Build your SaaS in 2 weeks - &lt;a href="https://codefa.st/?via=sevicdev" rel="noopener noreferrer"&gt;Start Now&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>api</category>
      <category>axios</category>
    </item>
    <item>
      <title>RabbitMQ container with Docker Compose</title>
      <dc:creator>Željko Šević</dc:creator>
      <pubDate>Mon, 02 Sep 2024 21:57:30 +0000</pubDate>
      <link>https://dev.to/zsevic/rabbitmq-container-with-docker-compose-4n8i</link>
      <guid>https://dev.to/zsevic/rabbitmq-container-with-docker-compose-4n8i</guid>
      <description>&lt;p&gt;Docker Compose facilitates spinning up a container for the RabbitMQ broker without installing it locally.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Docker Compose installed&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Configuration
&lt;/h3&gt;

&lt;p&gt;The following configuration spins up the RabbitMQ container with the management UI tool.&lt;/p&gt;

&lt;p&gt;The connection string for the RabbitMQ broker with &lt;code&gt;local&lt;/code&gt; virtual host is &lt;code&gt;amqp://localhost:5672/local&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;RabbitMQ management UI is available at the &lt;code&gt;http://localhost:15672&lt;/code&gt; link. Default credentials are &lt;code&gt;guest&lt;/code&gt; as username and &lt;code&gt;guest&lt;/code&gt; as password.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# docker-compose.yml&lt;/span&gt;
&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.8'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;rabbitmq&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rabbitmq:3-management&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;5672:5672&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;15672:15672&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;RABBITMQ_DEFAULT_VHOST=local&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rabbitmq_data:/data'&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;rabbitmq_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the following command to spin up the container.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Course
&lt;/h3&gt;

&lt;p&gt;Build your SaaS in 2 weeks - &lt;a href="https://codefa.st/?via=sevicdev" rel="noopener noreferrer"&gt;Start Now&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dockercompose</category>
      <category>rabbitmq</category>
    </item>
    <item>
      <title>Simulating keyboard typing with JavaScript</title>
      <dc:creator>Željko Šević</dc:creator>
      <pubDate>Wed, 21 Aug 2024 18:33:32 +0000</pubDate>
      <link>https://dev.to/zsevic/simulating-keyboard-typing-with-javascript-2p5d</link>
      <guid>https://dev.to/zsevic/simulating-keyboard-typing-with-javascript-2p5d</guid>
      <description>&lt;p&gt;Simulating keyboard typing in JavaScript can be useful for automating tasks or testing applications. The &lt;code&gt;KeyboardEvent&lt;/code&gt; API allows developers to trigger keyboard events programmatically.&lt;/p&gt;

&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The snippet below simulates pressing the &lt;code&gt;Ctrl + Enter&lt;/code&gt; command. The &lt;code&gt;bubbles&lt;/code&gt; flag ensures the event moves up through the DOM, so any elements higher up in the document can also detect and respond to it.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;KeyboardEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;keydown&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Enter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;ctrlKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;bubbles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatchEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The snippet below simulates pressing the &lt;code&gt;Shift + Enter&lt;/code&gt; command on a specific &lt;code&gt;input&lt;/code&gt; field.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;KeyboardEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;keydown&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Enter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;shiftKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;bubbles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;input&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;dispatchEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Course
&lt;/h3&gt;

&lt;p&gt;Build your SaaS in 2 weeks - &lt;a href="https://codefa.st/?via=sevicdev" rel="noopener noreferrer"&gt;Start Now&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>Profiling Node.js apps with Chrome DevTools profiler</title>
      <dc:creator>Željko Šević</dc:creator>
      <pubDate>Fri, 05 Jul 2024 00:22:43 +0000</pubDate>
      <link>https://dev.to/zsevic/profiling-nodejs-apps-with-chrome-devtools-profiler-313j</link>
      <guid>https://dev.to/zsevic/profiling-nodejs-apps-with-chrome-devtools-profiler-313j</guid>
      <description>&lt;p&gt;Profiling refers to analyzing and measuring an application's performance characteristics.&lt;/p&gt;

&lt;p&gt;Profiling helps identify performance bottlenecks in a Node.js app, such as CPU-intensive tasks like cryptographic operations, image processing, or complex calculations.&lt;/p&gt;

&lt;p&gt;This post covers running a profiler for various Node.js apps in Chrome DevTools.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Google Chrome installed&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Node.js app bootstrapped&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Run &lt;code&gt;node --inspect app.js&lt;/code&gt; to start the debugger.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open &lt;code&gt;chrome://inspect&lt;/code&gt;, click &lt;code&gt;Open dedicated DevTools for Node&lt;/code&gt; and then navigate to the Performance tab. Start recording.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run load testing via &lt;a href="https://www.npmjs.com/package/autocannon" rel="noopener noreferrer"&gt;autocannon&lt;/a&gt; package using the following command format &lt;code&gt;npx autocannon &amp;lt;COMMAND&amp;gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stop recording in Chrome DevTools.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Profiling
&lt;/h3&gt;

&lt;p&gt;On &lt;code&gt;Perfomance&lt;/code&gt; tab in Chrome DevTools open &lt;code&gt;Bottom-Up&lt;/code&gt; subtab to identify which functions consume the most time.&lt;/p&gt;

&lt;p&gt;Look for potential performance bottlenecks, such as synchronous functions for hashing (&lt;code&gt;pbkdf2Sync&lt;/code&gt;) or file system operations (&lt;code&gt;readFileSync&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Course
&lt;/h3&gt;

&lt;p&gt;Build your SaaS in 2 weeks - &lt;a href="https://codefa.st/?via=sevicdev" rel="noopener noreferrer"&gt;Start Now&lt;/a&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>chromedevtools</category>
      <category>profiling</category>
    </item>
    <item>
      <title>Load and stress testing with k6</title>
      <dc:creator>Željko Šević</dc:creator>
      <pubDate>Fri, 10 May 2024 20:47:16 +0000</pubDate>
      <link>https://dev.to/zsevic/load-and-stress-testing-with-k6-4d63</link>
      <guid>https://dev.to/zsevic/load-and-stress-testing-with-k6-4d63</guid>
      <description>&lt;p&gt;&lt;a href="https://k6.io" rel="noopener noreferrer"&gt;k6&lt;/a&gt; is a performance testing tool. This post explains types of performance testing and dives into &lt;code&gt;k6&lt;/code&gt; usage, from configuration to running tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Load and stress testing
&lt;/h3&gt;

&lt;p&gt;Load and stress testing are two types of performance testing used to evaluate how well a system performs under various conditions.&lt;/p&gt;

&lt;p&gt;Load testing determines how the system performs under expected user loads. The purpose is to identify performance bottlenecks.&lt;/p&gt;

&lt;p&gt;Stress testing assesses how the system performs when loads are heavier than usual. The purpose is to find the limit at which the system fails and to observe how it recovers from such failures.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://k6.io" rel="noopener noreferrer"&gt;k6&lt;/a&gt; installed&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Script (Node.js) file with configuration and execution function&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Configuration
&lt;/h3&gt;

&lt;p&gt;Configuration is stored inside &lt;code&gt;options&lt;/code&gt; variable, which allows you to set up different testing scenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;constant user load, the number of virtual users (vus) remains constant throughout the test period
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;vus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;10m&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;variable user load, the number of users increases and decreases over time
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;stages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1m&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;10m&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;5m&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Environment variables can be passed through the command line and are accessible within the script via the &lt;code&gt;__ENV&lt;/code&gt; object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;k6 &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;token run script.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Execution function
&lt;/h3&gt;

&lt;p&gt;This function defines what virtual users will do during the test. This function is called for each virtual user and typically includes steps that simulate user actions on the app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// Add more actions as required&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Test report
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;k6&lt;/code&gt; generates a report that provides detailed insights into various benchmarks, such as the number of virtual users, requests per second, request durations and error rates.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;This example utilizes &lt;code&gt;k6&lt;/code&gt; to conduct a load test using a variable user load approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;User simulation: The script ramps up to 1,000 users, maintains that level to simulate sustained traffic, and gradually reduces to zero.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Request handling: During the test, each virtual user sends a POST request to an API, with pauses between requests to mimic real user behavior.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Performance insights: After the test, k6 provides a report that shows key information, such as how fast the app responds and how many requests fail.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run it via &lt;code&gt;k6 -e TOKEN=1234 run script.js&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// script.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;check&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sleep&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;k6&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;scenario&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;k6/execution&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;k6/http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;stages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="c1"&gt;// Ramp up to 1000 users over 10 minutes&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;10m&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="c1"&gt;// Hold 1000 users for 30 minutes&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;30m&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="c1"&gt;// Ramp down to 0 users over 5 minutes&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;5m&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;iteration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;scenario&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;iterationInTest&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;Authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;__ENV&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TOKEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;response status was 200&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Course
&lt;/h3&gt;

&lt;p&gt;Build your SaaS in 2 weeks - &lt;a href="https://codefa.st/?via=sevicdev" rel="noopener noreferrer"&gt;Start Now&lt;/a&gt;&lt;/p&gt;

</description>
      <category>k6</category>
      <category>testing</category>
      <category>node</category>
    </item>
    <item>
      <title>Node Version Manager (nvm) overview</title>
      <dc:creator>Željko Šević</dc:creator>
      <pubDate>Wed, 08 May 2024 23:31:11 +0000</pubDate>
      <link>https://dev.to/zsevic/node-version-manager-nvm-overview-1bep</link>
      <guid>https://dev.to/zsevic/node-version-manager-nvm-overview-1bep</guid>
      <description>&lt;p&gt;&lt;code&gt;nvm&lt;/code&gt; facilitates switching between different Node versions across projects. This post covers its overview from installation to version management.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;To install &lt;code&gt;nvm&lt;/code&gt;, execute the following commands in your terminal. This example uses &lt;code&gt;zsh&lt;/code&gt;, but the process is similar for other shells like &lt;code&gt;bash&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-o-&lt;/span&gt; https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
&lt;span class="nb"&gt;source&lt;/span&gt; ~/.zshrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Version management
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Install the specific version. Including the &lt;code&gt;v&lt;/code&gt; prefix is optional.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nvm &lt;span class="nb"&gt;install &lt;/span&gt;v21.7.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Install the latest version
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nvm &lt;span class="nb"&gt;install &lt;/span&gt;node
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Install the latest one for the specified major version
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nvm &lt;span class="nb"&gt;install &lt;/span&gt;22
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Switch to a specific installed version
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nvm use 21
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Add &lt;code&gt;.nvmrc&lt;/code&gt; file inside the project directory and run &lt;code&gt;nvm use&lt;/code&gt; command to use the specified installed version.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;v21.7.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Get the list of locally installed versions
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nvm &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Get the list of available versions for installation
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nvm ls-remote
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Course
&lt;/h3&gt;

&lt;p&gt;Build your SaaS in 2 weeks - &lt;a href="https://codefa.st/?via=sevicdev" rel="noopener noreferrer"&gt;Start Now&lt;/a&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>nvm</category>
    </item>
    <item>
      <title>Debugging Node.js apps with Chrome DevTools debugger</title>
      <dc:creator>Željko Šević</dc:creator>
      <pubDate>Thu, 11 Apr 2024 23:59:52 +0000</pubDate>
      <link>https://dev.to/zsevic/debugging-nodejs-apps-with-chrome-devtools-debugger-50lf</link>
      <guid>https://dev.to/zsevic/debugging-nodejs-apps-with-chrome-devtools-debugger-50lf</guid>
      <description>&lt;p&gt;Debugging with a debugger and breakpoints is recommended rather than using console logs. Chrome provides a built-in debugger for JavaScript-based apps.&lt;/p&gt;

&lt;p&gt;This post covers configuring and running a debugger for various Node.js apps in Chrome DevTools.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Google Chrome installed&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Node.js app bootstrapped&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;p&gt;Open &lt;code&gt;chrome://inspect&lt;/code&gt;, click &lt;code&gt;Open dedicated DevTools for Node&lt;/code&gt; and open the Connection tab. You should see a list of network endpoints for debugging.&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;node --inspect-brk app.js&lt;/code&gt; to start the debugger, it will log the debugger network. Choose the network in Chrome to open the debugger in Chrome DevTools.&lt;/p&gt;

&lt;h3&gt;
  
  
  Debugging basics
&lt;/h3&gt;

&lt;p&gt;The variables tab shows local and global variables during debugging.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;step over next function call&lt;/code&gt; option goes to the following statement in the codebase, while the &lt;code&gt;step into next function call&lt;/code&gt; option goes deeper into the current statement.&lt;/p&gt;

&lt;p&gt;Add logs in the debug console via logpoints by selecting the specific part of the codebase so it logs when the selected codebase executes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Course
&lt;/h3&gt;

&lt;p&gt;Build your SaaS in 2 weeks - &lt;a href="https://codefa.st/?via=sevicdev" rel="noopener noreferrer"&gt;Start Now&lt;/a&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>chromedevtools</category>
      <category>debugging</category>
    </item>
    <item>
      <title>Sending e-mails with Sendgrid</title>
      <dc:creator>Željko Šević</dc:creator>
      <pubDate>Sat, 30 Mar 2024 00:44:02 +0000</pubDate>
      <link>https://dev.to/zsevic/sending-e-mails-with-sendgrid-4f4j</link>
      <guid>https://dev.to/zsevic/sending-e-mails-with-sendgrid-4f4j</guid>
      <description>&lt;p&gt;To send e-mails in a production environment, use services like &lt;a href="https://sendgrid.com/en-us" rel="noopener noreferrer"&gt;Sendgrid&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Verify the e-mail address on the &lt;a href="https://mc.sendgrid.com/senders" rel="noopener noreferrer"&gt;Sender Management page&lt;/a&gt; and create the SendGrid API key on the &lt;a href="https://app.sendgrid.com/settings/api_keys" rel="noopener noreferrer"&gt;API keys page&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;nodemailer&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;nodemailer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;emailConfiguration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EMAIL_USERNAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 'apikey'&lt;/span&gt;
      &lt;span class="na"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EMAIL_PASSWORD&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EMAIL_HOST&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 'smtp.sendgrid.net'&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EMAIL_PORT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 465&lt;/span&gt;
    &lt;span class="na"&gt;secure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EMAIL_SECURE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;transport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nodemailer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createTransport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;emailConfiguration&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendMail&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;"Sender" &amp;lt;sender@example.com&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;recipient1@example.com, recipient2@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Subject&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;b&amp;gt;Text&amp;lt;/b&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Message sent: %s&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messageId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Course
&lt;/h3&gt;

&lt;p&gt;Build your SaaS in 2 weeks - &lt;a href="https://codefa.st/?via=sevicdev" rel="noopener noreferrer"&gt;Start Now&lt;/a&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>nodemailer</category>
      <category>sendgrid</category>
    </item>
    <item>
      <title>MongoDB containers with Docker Compose</title>
      <dc:creator>Željko Šević</dc:creator>
      <pubDate>Fri, 02 Feb 2024 20:31:00 +0000</pubDate>
      <link>https://dev.to/zsevic/mongodb-containers-with-docker-compose-10hd</link>
      <guid>https://dev.to/zsevic/mongodb-containers-with-docker-compose-10hd</guid>
      <description>&lt;p&gt;Docker Compose facilitates spinning up a container for the MongoDB database without installing MongoDB locally.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Docker Compose installed&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Configuration
&lt;/h3&gt;

&lt;p&gt;The following configuration spins up the MongoDB container with the UI tool (Mongo Express).&lt;/p&gt;

&lt;p&gt;The connection string for the MongoDB database is &lt;code&gt;mongodb://localhost:27018&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Mongo Express is available at the &lt;code&gt;http://localhost:8082&lt;/code&gt; link. Use the below Basic auth credentials to log in to Mongo Express.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# docker-compose.yml&lt;/span&gt;
&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.8'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;mongo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mongo:7.0.5'&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;27018:27017&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;my-data:/var/lib/mongodb/data&lt;/span&gt;

  &lt;span class="na"&gt;mongo-express&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mongo-express:1.0.2'&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;8082:8081&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;ME_CONFIG_BASICAUTH_USERNAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;username&lt;/span&gt;
      &lt;span class="na"&gt;ME_CONFIG_BASICAUTH_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;password&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;my-data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the following command to spin up the containers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Course
&lt;/h3&gt;

&lt;p&gt;Build your SaaS in 2 weeks - &lt;a href="https://codefa.st/?via=sevicdev" rel="noopener noreferrer"&gt;Start Now&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dockercompose</category>
      <category>mongodb</category>
    </item>
    <item>
      <title>Web scraping with cheerio</title>
      <dc:creator>Željko Šević</dc:creator>
      <pubDate>Fri, 19 Jan 2024 19:11:30 +0000</pubDate>
      <link>https://dev.to/zsevic/web-scraping-with-cheerio-37el</link>
      <guid>https://dev.to/zsevic/web-scraping-with-cheerio-37el</guid>
      <description>&lt;p&gt;Web scraping means extracting data from websites. This post covers extracting data from the page's HTML tags.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;cheerio&lt;/code&gt; package is installed&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;HTML page is retrieved via an HTTP client&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Usage
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;create a scraper object with &lt;code&gt;load&lt;/code&gt; method by passing HTML content as an argument

&lt;ul&gt;
&lt;li&gt;set &lt;code&gt;decodeEntities&lt;/code&gt; option to false to preserve encoded characters (like &amp;amp;) in their original form
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;div&amp;gt;&amp;lt;!-- HTML content --&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;decodeEntities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;find DOM elements by using CSS-like selectors
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.item&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;iterate through found elements using &lt;code&gt;each&lt;/code&gt; method
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;access element content using specific methods&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;text &lt;code&gt;$(element).text()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;HTML &lt;code&gt;$(element).html()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;attributes

&lt;ul&gt;
&lt;li&gt;all &lt;code&gt;$(element).attr()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;specific one &lt;code&gt;$(element).attr('href')&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;child elements

&lt;ul&gt;
&lt;li&gt;first &lt;code&gt;$(element).first()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;last &lt;code&gt;$(element).last()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;all &lt;code&gt;$(element).children()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;specific one &lt;code&gt;$(element).find('a')&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;siblings

&lt;ul&gt;
&lt;li&gt;previous &lt;code&gt;$(element).prev()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;next &lt;code&gt;$(element).next()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Disclaimer
&lt;/h3&gt;

&lt;p&gt;Please check the website's terms of service before scraping it. Some websites may have terms of service that prohibit such activity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Course
&lt;/h3&gt;

&lt;p&gt;Build your SaaS in 2 weeks - &lt;a href="https://codefa.st/?via=sevicdev" rel="noopener noreferrer"&gt;Start Now&lt;/a&gt;&lt;/p&gt;

</description>
      <category>scraping</category>
      <category>cheerio</category>
      <category>node</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
