<?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: Flagsmith</title>
    <description>The latest articles on DEV Community by Flagsmith (@flagsmith).</description>
    <link>https://dev.to/flagsmith</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%2Forganization%2Fprofile_image%2F7816%2Fe5c477e8-6cb4-4526-bf0d-1beaea608971.png</url>
      <title>DEV Community: Flagsmith</title>
      <link>https://dev.to/flagsmith</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/flagsmith"/>
    <language>en</language>
    <item>
      <title>Five Open Source tools to track your PostgreSQL database performance</title>
      <dc:creator>Kyle Johnson</dc:creator>
      <pubDate>Tue, 28 Jan 2025 14:34:32 +0000</pubDate>
      <link>https://dev.to/flagsmith/five-open-source-tools-to-track-your-postgresql-database-performance-3gki</link>
      <guid>https://dev.to/flagsmith/five-open-source-tools-to-track-your-postgresql-database-performance-3gki</guid>
      <description>&lt;p&gt;Written by Eddie Jaoude (see outro)&lt;/p&gt;

&lt;p&gt;How is your PostgreSQL (aka Postgres) database performing in production after releasing that latest shiny new feature? If you don’t measure its performance then you will never know and the best you can hope for is an educated guess. Do you want to rely on guesswork to decide whether you should be rolling out this new feature to your users? &lt;/p&gt;

&lt;p&gt;In this blog post I will take you through the steps to achieve/create a dashboard that monitors a PostgreSQL database. The dashboard will also be annotated when we enable/disable features. This is an effective way of monitoring the impact that enabling a new feature has on a database. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0htmsw97xq9hyvwq6chx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0htmsw97xq9hyvwq6chx.png" alt="Using Grafana with Flagsmith" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All tools that I refer to in this blog post are Open Source and free:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NextJS for our app &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;https://nextjs.org/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;PostgreSQL as our database &lt;a href="https://www.postgresql.org/" rel="noopener noreferrer"&gt;https://www.postgresql.org/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;PostgreSQL Exporter to expose metrics -&lt;a href="https://github.com/prometheus-community/postgres_exporter" rel="noopener noreferrer"&gt;https://github.com/prometheus-community/postgres_exporter&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Prometheus to collect metrics &lt;a href="https://prometheus.io/" rel="noopener noreferrer"&gt;https://prometheus.io/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Grafana to display metrics &lt;a href="https://grafana.com/" rel="noopener noreferrer"&gt;https://grafana.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Flagsmith for feature flag management &lt;a href="https://www.flagsmith.com/" rel="noopener noreferrer"&gt;https://www.flagsmith.com/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;So that you can follow along please make sure that you have the following: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Flagsmith (I will use their free cloud account, but you can also host it yourself on Docker).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;I will be using the following architecture setup, however you can move any items between any of the layers to better suit your situation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Host machine&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Our Application (NextJS)&lt;/li&gt;
&lt;li&gt;K6 to simulate users&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Docker&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;PostgreSQL database&lt;/li&gt;
&lt;li&gt;PostgreSQL Exporter&lt;/li&gt;
&lt;li&gt;Prometheus&lt;/li&gt;
&lt;li&gt;Grafana&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Cloud&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Flagsmith (you can run this in Docker if you prefer)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F941fqsyy1gbjfsndafqa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F941fqsyy1gbjfsndafqa.png" alt="Architecture Diagram" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  PostgreSQL
&lt;/h2&gt;

&lt;p&gt;For this blog I will be using the SQL database Postgres. Postgres is a popular Open Source relational database that is super robust and stable with decades of experience. I find it has a great balance of the latest trending features without compromising stability. I have used Postgres in projects for startups to UK banks, and it handles a variety of different data and performance situations without skipping a beat. &lt;/p&gt;

&lt;p&gt;If you already have a PostgreSQL database then please feel free to skip this section.&lt;/p&gt;

&lt;p&gt;This Docker command will create a PostgreSQL 14 database. Set the username and password as well as expose the port on our local machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt; postgres14 &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;user &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;password &lt;span class="nt"&gt;-p&lt;/span&gt; 5432:5432 &lt;span class="nt"&gt;-d&lt;/span&gt; postgres:14
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a small private network for all our Docker containers to communicate together:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker network create postgres-network
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then add the new PostgreSQL database to this private network. This is achieved by using the container name we created before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker network connect postgres-network postgres14
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you can inspect the network to get the PostgreSQL database’s IP with this command and specify the name of the network to inspect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker network inspect postgres-network
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the JSON output there will be a “Container” section that lists the containers in the network and also their respective IP. You will need the PostgreSQL IP in the next section.&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;"Containers"&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;"4469e0602d83ac7fa2bd70ecbbcb34c41911cc342506c0f0a67f71365a61d54a"&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;"Name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"postgres14"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"EndpointID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"5c8a26405db3598f472e9dcb4217b7b0f1d117974a5e2981e301bcda850a99e1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"MacAddress"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"02:42:ac:12:00:04"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"IPv4Address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"172.18.0.2/16"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"IPv6Address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  PostgreSQL Exporter
&lt;/h2&gt;

&lt;p&gt;Now we have a database, we need to get the performance metrics out from it. The PostgreSQL Exporter is the industry standard way to gather PostgreSQL metrics for Prometheus consumption. It is a stable project that has been around for many years and is still getting new features added all the time. At the time of writing this “Multi-Target Support” has been added as a beta feature. With plenty of content and use cases out there, you will not be short of examples to match your situation.&lt;/p&gt;

&lt;p&gt;To get the Docker container running we need to pass some more parameters. In addition to the Docker container name and exposing the port, specify the PostgreSQL database IP (you can get this from the end of the previous section using the Docker inspect command), the PostgreSQL database username and password.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run --name postgres-exporter -p 9187:9187 -e DATA_SOURCE_URI="172.18.0.2:5432/postgres?sslmode=disable" -e DATA_SOURCE_USER=user -e DATA_SOURCE_PASS=password -d quay.io/prometheuscommunity/postgres-exporter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As before, add the new container to the private Docker network with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker network connect postgres-network postgres-exporter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Test the PostgreSQL Exporter is working by visiting this url in the browser or using curl on your host machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl "http://localhost:9187/metrics"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can learn more about the PostgreSQL Exporter in their GitHub repository &lt;a href="https://github.com/prometheus-community/postgres_exporter" rel="noopener noreferrer"&gt;https://github.com/prometheus-community/postgres_exporter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next inspect the private network again for the PostgreSQL Exporter IP, as this will be needed in the following section:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker network inspect postgres-network
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Prometheus
&lt;/h2&gt;

&lt;p&gt;At this stage we have a database and we have the performance metrics, but we need to store the collected data over time. Prometheus is the go to Open Source tool for “metrics to insight” built with monitoring and alerting in mind. It stores the data in a time series format and has many integrations with popular tools and platforms. With great documentation, an active GitHub repo (50k+ Stars), and a large community, it is no surprise that Prometheus is the go to tool.&lt;/p&gt;

&lt;p&gt;Although Prometheus has a big ecosystem it is straightforward to get started. All we will need is a small YAML file and one Docker command.&lt;/p&gt;

&lt;p&gt;Create a YAML file called “prometheus.yml”. You can keep this anywhere you prefer, but I have chosen to do so in my “Downloads” folder (full path “~/Downloads/prometheus.yml”).&lt;/p&gt;

&lt;p&gt;In this file, first set global configs for “scrape_interval” and “evaluation_interval”. Note these global configs can be overwritten at the job level if required when having multiple jobs.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;scrape_interval&lt;/strong&gt;: defines how often the monitor is scraped - you can change this to your preference, I have selected 15 seconds here.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;evaluation_interval&lt;/strong&gt;: defines how often queries are evaluated for alerting.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is recommended in most cases to have both these global configs set at the same value.&lt;/p&gt;

&lt;p&gt;Below the global configs, we specify the jobs under “scrape_configs”, this is made up of the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;job_name&lt;/strong&gt;: you can call this the name you prefer, it will show in your Prometheus web page of targets (screenshot below)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;static_configs&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;targets&lt;/strong&gt;: this is the IP and port to scrape of the “Postgres Exporter” in this example. Use the IP from the last Docker command in the previous section.
&lt;/li&gt;
&lt;/ul&gt;


&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;global&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;scrape_interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;15s&lt;/span&gt;
  &lt;span class="na"&gt;evaluation_interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;15s&lt;/span&gt;

&lt;span class="na"&gt;scrape_configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;job_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;postgres-exporter"&lt;/span&gt;
    &lt;span class="na"&gt;static_configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;targets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;172.18.0.3:9187"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now to run the Prometheus Docker container to use the YAML config file just created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; prometheus &lt;span class="nt"&gt;-p&lt;/span&gt; 9090:9090 &lt;span class="nt"&gt;-v&lt;/span&gt; ~/Downloads/prometheus.yml:/etc/prometheus/prometheus.yml &lt;span class="nt"&gt;-d&lt;/span&gt; prom/prometheus
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last step in this section is to add our new Prometheus container to the private network we created. Use the following command to do this is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker network connect postgres-network prometheus
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then visit &lt;a href="http://localhost:9090/targets" rel="noopener noreferrer"&gt;http://localhost:9090/targets&lt;/a&gt; and you will see the job and the state of “UP”:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgkn8eub0efo82u92q3e4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgkn8eub0efo82u92q3e4.png" alt="Prometheus targets" width="800" height="231"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note: If you stop the Prometheus container, it will no longer have access to the private network. Therefore you will need to add it back to the network created so it has access to the other containers. If you have restarted other containers also check none of their container IPs have changed, as these might need updating in the config files and also network.&lt;br&gt;
You can also learn more about Prometheus on their official website: &lt;a href="https://prometheus.io/docs/introduction/overview/" rel="noopener noreferrer"&gt;https://prometheus.io/docs/introduction/overview/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Grafana
&lt;/h2&gt;

&lt;p&gt;Now we have our Postgres performance metrics stored, we need to visualise the data. Grafana visualises, queries and alerts on our data from multiple sources including Prometheus as well as NoSQL/SQL databases. With Grafana being so popular and customizable, it has a large community with pre-existing templates to kickstart our Grafana dashboard and then we can customize as needed.&lt;/p&gt;

&lt;p&gt;Grafana can run on Docker with one command, which uses port 3000. I will map this externally to port 3001 on my host machine because my NextJS is already using port 3000:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 3001:3000 &lt;span class="nt"&gt;--name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;grafana grafana/grafana-enterprise
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the new container to our network:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker network connect postgres-network grafana
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Visit the Grafana Dashboard &lt;a href="http://localhost:3001" rel="noopener noreferrer"&gt;http://localhost:3001&lt;/a&gt; in the browser. You can log in with the username “admin” and the password “admin” - you will be prompted to update the password, but if running Grafana locally you can click the “skip” button for now.&lt;/p&gt;

&lt;p&gt;Firstly open the side menu and expand “Connections” and click “Data source”. Then you can click “Add data source” for Prometheus.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmr5fi1ry7rfakwewu7dd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmr5fi1ry7rfakwewu7dd.png" alt="Grafana data sources" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsdd7w1o4t840zojwhi2k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsdd7w1o4t840zojwhi2k.png" alt="Grafana add Data source" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select Prometheus and you will need to add the Prometheus URL. You can get the IP by inspecting the Docker network again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker network inspect postgres-network
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frjvb14yt74tvqe5uk1id.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frjvb14yt74tvqe5uk1id.png" alt="Prometheus container" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Only the Prometheus URL is required (don’t forget to add the port). The other fields are optional and can be updated later if required:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8bsg47iagiuznhq7fmit.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8bsg47iagiuznhq7fmit.png" alt="Prometheus connection" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now there is a data source, a great place to start a Grafana Dashboard is from an existing template and customise it further from there. &lt;/p&gt;

&lt;p&gt;Visit your Grafana Dashboard on &lt;a href="http://localhost:3001/dashboard/import" rel="noopener noreferrer"&gt;http://localhost:3001/dashboard/import&lt;/a&gt; and paste in the templated Grafana Dashboard URL &lt;a href="https://grafana.com/grafana/dashboards/455-postgres-overview/" rel="noopener noreferrer"&gt;https://grafana.com/grafana/dashboards/455-postgres-overview/&lt;/a&gt; and then click “load”. A new form will appear and you can rename the dashboard, but the important part is to select a Prometheus source.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzyii5yme8a6tozdmmrhc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzyii5yme8a6tozdmmrhc.png" alt="Import Prometheus dashboard" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My imported Grafana Dashboard looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjpx152q6ivdz6iq8dkwh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjpx152q6ivdz6iq8dkwh.png" alt="Grafana Dashboard" width="800" height="671"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;List your running Docker containers with this command and you should see the following containers running:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu4phklinxbbupnzohc82.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu4phklinxbbupnzohc82.png" alt="Docker ps" width="800" height="74"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to read more about Grafana then check out their website: &lt;a href="https://grafana.com/docs/grafana/latest/" rel="noopener noreferrer"&gt;https://grafana.com/docs/grafana/latest/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Flagsmith
&lt;/h2&gt;

&lt;p&gt;We have all been there where our project needs some feature flags and we think we are being smart by moving them to a config file or environment variable. In reality we still need to deploy to make changes and the developers/devops in the team will need to make those changes. Plus they are not instant and usually require a full redeploy. &lt;/p&gt;

&lt;p&gt;To manage my feature flags, I don’t like to reinvent the wheel, so I use the Open Source project Flagsmith and their cloud platform. Flagsmith has more features than I could ever create, plus it allows me to ship faster and more confidently by decoupling my deployments and releases as well as other great features that allow me to release to specific users or groups of users before everyone.&lt;/p&gt;

&lt;p&gt;With Flagsmith we can not only toggle this feature on/off but we can also expose it to specific people or groups of people.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sign up
&lt;/h3&gt;

&lt;p&gt;First start by signing up to Flagsmith's free account &lt;a href="https://www.flagsmith.com/" rel="noopener noreferrer"&gt;https://www.flagsmith.com/&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Once you sign up / log in, you will create an “Organisation” and then a “Project”:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F27lpnfor3nhs9i6yzr9w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F27lpnfor3nhs9i6yzr9w.png" alt="Flagsmith Project" width="800" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a feature flag
&lt;/h2&gt;

&lt;p&gt;Click the “Create Feature” button at the top right.&lt;br&gt;
Give the feature a name. One thing to take into consideration is that you cannot change the name later.&lt;br&gt;
Leave “Enabled by default” off.&lt;/p&gt;

&lt;p&gt;“Value” is not needed for our feature as we will use enable/disable only. Value would be used for controlling the content. For example when to show a banner and the content of the banner.&lt;br&gt;
You can also give a “Description”, but note that you can change this later.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzx6zes52psxfhudgxk2b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzx6zes52psxfhudgxk2b.png" alt="Create a feature flag in Flagsmith" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Create a feature flag
&lt;/h2&gt;

&lt;p&gt;Flagsmith has many integrations so do make sure that you check out their great documentation. &lt;/p&gt;

&lt;p&gt;To use Flagsmith with NextJS, add it as an npm dependency with the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i flagsmith &lt;span class="nt"&gt;--save&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a NextJS provider in file “src/app/providers.js”:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use client&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;FlagsmithProvider&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="s2"&gt;flagsmith/react&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;createFlagsmithInstance&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="s2"&gt;flagsmith/isomorphic&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;useRef&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="s2"&gt;react&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="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Providers&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;serverState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&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;flagsmithInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;createFlagsmithInstance&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;FlagsmithProvider&lt;/span&gt;
      &lt;span class="nx"&gt;flagsmith&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;flagsmithInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;serverState&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;serverState&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/FlagsmithProvider&lt;/span&gt;&lt;span class="err"&gt;&amp;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;Open the “src/app/layout.js” file and in the import section add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createFlagsmithInstance&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="s2"&gt;flagsmith/isomorphic&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;Providers&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Providers&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;p&gt;Then in the RootLayout function add (don’t forget to make the function async):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;flagsmith&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createFlagsmithInstance&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;flagsmith&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;environmentID&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;NEXT_PUBLIC_FLAGSMITH_ID&lt;/span&gt;&lt;span class="p"&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;serverState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;flagsmith&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getState&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="nx"&gt;serverState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// just to check the data is coming through&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wrap the “body” in the provider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Providers&lt;/span&gt; &lt;span class="nx"&gt;serverState&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;serverState&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;inter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;className&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="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/body&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Providers&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly add your &lt;strong&gt;“NEXT_PUBLIC_FLAGSMITH_ID”&lt;/strong&gt; to the “.env” file, which you can find in the “SDK Keys” menu on the left of your Flagsmith Dashboard. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi3dnrdb6qqh8iwm08ypa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi3dnrdb6qqh8iwm08ypa.png" alt="Flagsmith SDK key" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your “.env” file should look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NEXT_PUBLIC_FLAGSMITH_ID=3C5QvbtgZ3C5Qvbxyz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s run the app and check it all works together as expected:&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 dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There should be no visual change in the UI, but in the terminal there will be a further output from Flagsmith because of our &lt;code&gt;console.log&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In my terminal I have the following output which contains the feature flags I created in Flagsmith. (Currently I only have one feature flag, if there were more you would see them in the output also.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; ✓ Compiled &lt;span class="k"&gt;in &lt;/span&gt;101ms &lt;span class="o"&gt;(&lt;/span&gt;496 modules&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
  api: &lt;span class="s1"&gt;'https://edge.api.flagsmith.com/api/v1/'&lt;/span&gt;,
  environmentID: &lt;span class="s1"&gt;'3C5QvbtgZh3C5QvbtgZh'&lt;/span&gt;,
  flags: &lt;span class="o"&gt;{&lt;/span&gt;
    stats: &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="nb"&gt;id&lt;/span&gt;: 98466,
      enabled: &lt;span class="nb"&gt;false&lt;/span&gt;,
      value: &lt;span class="s1"&gt;''&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;,
  identity: undefined,
  ts: null,
  traits: &lt;span class="o"&gt;{}&lt;/span&gt;,
  evaluationEvent: null
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Use Feature Flag
&lt;/h2&gt;

&lt;p&gt;On my homepage, I am thinking of showing some near real-time statistics but I am concerned about the impact. By wrapping it in a Flagsmith Feature Flag, I can enable it for my user, a group of users or for everyone, as well as disable it if required. I have created a Stats component that I will include on the homepage, and in the Stats component it will check for the Feature Flag “stats” status.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use client&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;useFlags&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="s2"&gt;flagsmith/react&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="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Stats&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;stats&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useFlags&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stats&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return &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;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can show/hide these stats from the Flagsmith Dashboard.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnuzofu3f28vheuvtkvv6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnuzofu3f28vheuvtkvv6.png" alt="View features in Flagsm9ith" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrate with Grafana
&lt;/h2&gt;

&lt;p&gt;It is important to know when we toggle on/off features in our app what the direct impact on the application’s performance is. Yes we could try and guess what happened when, but this is neither efficient nor accurate. It is much better to integrate Flagsmith with Grafana, so that it actually puts a marker (called a “Grafana Annotation”) on the graph for us.&lt;/p&gt;

&lt;p&gt;The integration is straightforward. However we need to expose our Grafana instance to the internet so Flagsmith in the cloud can communicate with it. &lt;/p&gt;

&lt;p&gt;If you are not using Flagsmith cloud and your Flagsmith instance is local to your Grafana or your Grafana is on the internet already (because you are using Grafana cloud), then you can skip this section. &lt;/p&gt;

&lt;p&gt;There are multiple ways to achieve this, but my preferred way is to use an npm package which results in a total of using two commands:&lt;/p&gt;

&lt;p&gt;Install the npm package “localtunnel” globally with the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; localtunnel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tell localtunnel what port to expose to the internet and forward to my local instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lt &lt;span class="nt"&gt;--port&lt;/span&gt; 3001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will return us a URL that can be used for the integration on Flagsmith.It is therefore important to remember this URL as it will be needed for the next step on the Flagsmith’s Dashboard.&lt;/p&gt;

&lt;p&gt;Get a “service account token” from your Grafana.This can be done by opening the side menu and clicking “Users and access”, then “Service accounts”. Then give the service account a name.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6mckz1zqe00egvb4pidj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6mckz1zqe00egvb4pidj.png" alt="Grafana create service account" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the newly created service account, create a token.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuxmoept3tf7ajxlvtflv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuxmoept3tf7ajxlvtflv.png" alt="Create Grafana service account token" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy this token to your clipboard as you will need it in the next step on the Flagsmith Dashboard.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy2crva2tva7ybor83yb6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy2crva2tva7ybor83yb6.png" alt="Copy Grafana service account token" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go to the Flagsmith Dashboard and click on “Integrations”:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkgnsywcbec0cr1qfk30w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkgnsywcbec0cr1qfk30w.png" alt="Flagsmith integrations" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then scroll down to “Grafana” and click on “Add Integration”. Add the URL that was generated in the terminal and the “service account token” previously copied.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi43jhn28qbqwcl9lu49a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi43jhn28qbqwcl9lu49a.png" alt="Create Grafana integration in Flagsmith" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you will see the integration is complete.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9q75aqzr4emwev1ieitt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9q75aqzr4emwev1ieitt.png" alt="Grafana integration in Flagsmith" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The final step is to display the Flagsmith feature flag changes on the Grafana Dashboard. We will need to edit the Grafana Dashboard we imported earlier to add the annotation as it occurs. &lt;/p&gt;

&lt;p&gt;Go back to the Grafana Dashboard created earlier and press “Edit”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Friyli67d8ig7xip6w23n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Friyli67d8ig7xip6w23n.png" alt="Edit Grafana Dashboard" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the Grafana Dashboard settings click the “Annotations” tab and then “Add annotation query”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftm4jk0bcdgnvvm3sh7e3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftm4jk0bcdgnvvm3sh7e3.png" alt="Grafana annotations" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Give the annotation a name and select “Grafana” for the data source. For the filter drop down select “Tags” and select the tags you are interested in - I selected my whole Flagsmith project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6z8zhh96mqj2yw5w9xjz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6z8zhh96mqj2yw5w9xjz.png" alt="Create Flagsmith Grafana annotation" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Save the annotation changes to the Grafana Dashboard and exit edit mode, returning to the main Grafana Dashboard view. You will now have a “Flagsmith” toggle at the top of the Grafana Dashboard to show/hide the annotations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fddutvvo3lmcqboauozts.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fddutvvo3lmcqboauozts.png" alt="Grafana Flagsmith toggle" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With this toggle enabled, each time changes are made on the Flagsmith Dashboard they will appear on the Grafana Dashboard. I will demonstrate this shortly but first, I will generate some user load to make the graphs more interesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  k6
&lt;/h2&gt;

&lt;p&gt;Simulating and creating user traffic can be tricky. There are many tools out there and I have tried and used many over the years. Recently I came across k6. This is a load testing tool created by Grafana. It is designed to be developer friendly, from browser performance testing to chaos and resilience testing. k6 has packages for the popular operating systems as well as a Docker container and a standalone binary.&lt;/p&gt;

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

&lt;p&gt;I will install k6 on my Mac with brew:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Script
&lt;/h3&gt;

&lt;p&gt;In k6’s Getting Started guide, they have some great example scripts to get started. I have taken their “Ramp VUs up and down in stage” and modified them a little for my needs.&lt;/p&gt;

&lt;p&gt;The script has the imports at the top as you would expect, followed by the test configuration. In the configuration there are an array of “stages” where each item is an object of “duration” and “target”. In this “stages” array you can ramp up and down the users at specific times.&lt;/p&gt;

&lt;p&gt;After exporting the config options, export a default function with the URL k6 will make the request against and then validate the response, in this case we are expecting a status code of 200.&lt;/p&gt;

&lt;p&gt;I will add the following k6 script to a file called “script.js” in the root of the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&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="s2"&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;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="s2"&gt;k6&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Test configuration&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;thresholds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Assert that 99% of requests finish within 3000ms.&lt;/span&gt;
    &lt;span class="na"&gt;http_req_duration&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="s2"&gt;p(99) &amp;lt; 3000&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="c1"&gt;// Ramp the number of virtual users up and down&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="s2"&gt;30s&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;100&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="s2"&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;50&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="s2"&gt;3m&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="s2"&gt;20s&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="c1"&gt;// Simulated user behavior&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;res&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;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:3000&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// Validate response status&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;res&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="s2"&gt;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;r&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;r&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;p&gt;To run the above k6 script, use the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;k6 run script.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output is:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdyzj9cod99kosbv4g2pk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdyzj9cod99kosbv4g2pk.png" alt="k6 Output" width="800" height="516"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While k6 is running, we can toggle our Flagsmith feature on/off and see the effect it has on the application. Each time changes on the Flagsmith’s Dashboard are made the annotation appears and we can hover the annotating line to get more information.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk01e545qvmua96triltq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk01e545qvmua96triltq.png" alt="Flagsmith annotations" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you can test in production and make an informed decision as to whether you should roll out the new feature to everyone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;p&gt;You might find yourself having connection issues between the containers during setup. Or the setup initially worked but after restarting one or more containers or your host machine, it no longer works. I found that this is usually due to IP changes, which caught me out multiple times before. &lt;/p&gt;

&lt;p&gt;Note that you might not get any visible errors in the logs, but no data will be coming through the workflow. Check the IP of each container and make sure it is in the private network and the relative YAML config files are updated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;What effect does your latest feature have on your app’s health? If you can’t quantify the impact, how do you know if you should or should not roll it out to all your users? There is no need to build scripts and tooling to capture then measure the performance of your app before and after changes. This is complex and time consuming, especially when you could be using this time to focus on your app. There are so many Open Source tools that you can use and integrate together to help you measure performance and improve your product, allowing you to focus on what you can deliver and the benefits to your users. Plus if you don’t want to host and manage these tools most of them have cloud versions you can also use.&lt;/p&gt;

&lt;p&gt;Having a strong foundation for your project will help you make more informed decisions rather than guessing. &lt;/p&gt;

&lt;p&gt;When you find yourself in the situation when something happened to your production app and you are trying to understand the “how” and “why” while debugging the situation, if you have not captured the historic information, then this becomes very difficult. &lt;/p&gt;

&lt;p&gt;Key takeaways: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;1: You can’t improve what you don’t measure. Measure before and after the changes so you can compare the impact these changes have on your project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;2: Be proactive. Simulate user load and see how your product performs; one user is different to 1000 users.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;3: Use feature flags to safely and confidently test in production without affecting your users, which will allow you to make more accurate decisions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Be proactive with all your changes, know the impact, and be confident to deploy on a Friday!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;About the Author&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Eddie is passionate about technologies and products which contribute towards a developer's work becoming more efficient and high quality.&lt;/p&gt;

&lt;p&gt;Eddie uses his 15+ years of Fullstack expertise to offer personalised consulting on Open Source best practices, as well as creating technical content to bring awareness, review and teach his clients' latest products and services, to the tech community. To name a few areas, Eddie has a keen interest in Javascript/Typescript, API, databases and DevOps.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.eddiejaoude.io/" rel="noopener noreferrer"&gt;https://www.eddiejaoude.io/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://eddiejaoude.substack.com/links" rel="noopener noreferrer"&gt;http://eddiejaoude.substack.com/links&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>grafana</category>
      <category>flagsmith</category>
      <category>prometheus</category>
    </item>
    <item>
      <title>5 Open-Source Repositories for Faster Development in Monolithic Architecture</title>
      <dc:creator>annaredbond</dc:creator>
      <pubDate>Mon, 06 Nov 2023 15:29:01 +0000</pubDate>
      <link>https://dev.to/flagsmith/5-open-source-repositories-for-faster-development-in-monolithic-architecture-52c0</link>
      <guid>https://dev.to/flagsmith/5-open-source-repositories-for-faster-development-in-monolithic-architecture-52c0</guid>
      <description>&lt;p&gt;Many companies choose to level up their feature flags and come to &lt;a href="https://www.flagsmith.com/?utm_source=dev&amp;amp;utm_medium=listicle&amp;amp;utm_campaign=monolith&amp;amp;utm_id=devto" rel="noopener noreferrer"&gt;Flagsmith&lt;/a&gt; because they’re moving from a monolith to a microservice architecture. However, as engineers, we find ourselves moving in the monolith direction to support them. We even &lt;a href="https://www.flagsmith.com/blog/embracing-the-monolith" rel="noopener noreferrer"&gt;chose to build our monolith&lt;/a&gt; and write about that decision. &lt;/p&gt;

&lt;p&gt;The monolith vs microservice argument rages on, but there’s no right answer. There’s also no silver bullet! Architecture should always be driven by the use case, business, and product. &lt;/p&gt;

&lt;p&gt;If you’re building in a monolith, it helps to use tools that can let you release faster without having to build the functionality yourself. That lets you focus on your &lt;em&gt;core&lt;/em&gt; business and application. &lt;/p&gt;

&lt;p&gt;Here are five open-source repositories that can lead to a safer and more productive development process in monolithic environments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcqpb95hgnf61o9r1a5j2.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcqpb95hgnf61o9r1a5j2.gif" alt="GIF of a minecraft block going into a gap"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://www.flagsmith.com/?utm_source=dev&amp;amp;utm_medium=listicle&amp;amp;utm_campaign=monolith&amp;amp;utm_id=devto" rel="noopener noreferrer"&gt;1. Flagsmith: Feature Flags&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjsj8vjsccc1z61izre77.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjsj8vjsccc1z61izre77.png" alt="Flagsmith Logo on a dark purple background"&gt;&lt;/a&gt;&lt;br&gt;
Feature flags give you a safety net to push code and not break the application. (This is especially important for monoliths.) Ship to production with the security of a safety flag and avoid impacting user experience.&lt;/p&gt;

&lt;p&gt;With feature flags, you can release gradually and run beta tests to select groups of users before pushing for wider adoption. You can also run &lt;a href="https://www.flagsmith.com/a-b-and-multivariate-testing" rel="noopener noreferrer"&gt;A/B tests&lt;/a&gt; to experiment and make data-driven decisions before pushing application changes to your whole user base.  &lt;/p&gt;

&lt;p&gt;Flagsmith is an open-source tool that lets you manage your feature flags. You can also monitor the impact of features, implement kill switches, and quickly roll back without having to redeploy. &lt;/p&gt;

&lt;p&gt;Star the GitHub repo ⭐: &lt;a href="https://github.com/flagsmith/flagsmith" rel="noopener noreferrer"&gt;https://github.com/flagsmith/flagsmith&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  2. &lt;a href="https://github.com/boxyhq/" rel="noopener noreferrer"&gt;BoxyHQ: Security and Authentication&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbd38tsbkxuvzt6hn5abq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbd38tsbkxuvzt6hn5abq.png" alt="BoxyHQ logo on a dark purple background"&gt;&lt;/a&gt;&lt;br&gt;
Security is vital when deploying in a monolithic environment. BoxyHQ lets you avoid having to build your own authentication mechanism, observability, or methods for dealing with encrypting secrets and tracking sensitive data.&lt;/p&gt;

&lt;p&gt;BoxyHQ provides the building blocks for safely deploying in a monolith. It has a suite of APIs for security and privacy, designed to help engineering teams build and ship compliant cloud applications faster.&lt;/p&gt;

&lt;p&gt;Focus on building your core product without sacrificing security or worrying about enterprise readiness. It offers features like Enterprise SSO, Directory Sync, Audit Logs, and a Privacy Vault for protecting sensitive data.&lt;/p&gt;

&lt;p&gt;Star the GitHub repo ⭐: &lt;a href="https://github.com/boxyhq/jackson" rel="noopener noreferrer"&gt;https://github.com/boxyhq/jackson&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  3. Firecamp: API Testing and Debugging
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1yqq907swou9r9sk0mf6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1yqq907swou9r9sk0mf6.png" alt="Firecamp API logo on a dark purple background"&gt;&lt;/a&gt;&lt;br&gt;
Testing and debugging APIs is critical when building robust and reliable applications, yet it can be challenging in a monolithic codebase.  Products like Postman exist, though they aren’t open source. &lt;/p&gt;

&lt;p&gt;For a top-notch Developer experience, Firecamp offers API testing and debugging. Firecamp allows API collections, automated documentation, integrations with CI/CD tooling, and so on. This ensures the safety and reliability of APIs in a monolithic system. Plus, it’s open source. &lt;/p&gt;

&lt;p&gt;Star the GitHub repo ⭐: &lt;a href="https://github.com/firecamp-dev" rel="noopener noreferrer"&gt;https://github.com/firecamp-dev&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Prometheus: Monitoring and Alerting
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqjl3c5bua13zb2go46x6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqjl3c5bua13zb2go46x6.png" alt="Prometheus logo on a dark purple background"&gt;&lt;/a&gt;&lt;br&gt;
With a monolith, you want metrics—and the history of those metrics. You want to be able to generate alerts and charts so that you can make sense of the metrics. &lt;/p&gt;

&lt;p&gt;Prometheus lets you set up effective monitoring and ensure the system stability of your monolith. It can help identify and address issues before they impact the production environment.&lt;/p&gt;

&lt;p&gt;Star the GitHub repo ⭐: &lt;a href="https://github.com/prometheus/prometheus" rel="noopener noreferrer"&gt;https://github.com/prometheus/prometheus&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  5. Novu: Version Control and Notifications
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fplnvkpx5e1loizj2k8xi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fplnvkpx5e1loizj2k8xi.png" alt="Novu logo on a dark purple background"&gt;&lt;/a&gt;&lt;br&gt;
Version control is vital in monolithic environments. So is communicating with users in your app. &lt;/p&gt;

&lt;p&gt;Novu offers simple components and APIs for managing user communication across all channels in one place. Manage user content without needing to redeploy your code—and risk affecting your monolith. &lt;/p&gt;

&lt;p&gt;Star the GitHub repo ⭐: &lt;a href="https://github.com/novuhq/novu" rel="noopener noreferrer"&gt;https://github.com/novuhq/novu&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;These tools can be used together to develop faster—but still safely—in a monolithic architecture. Plus, they’re open-source! &lt;/p&gt;

&lt;p&gt;Try them out, check the code, and give them a star. 🚀 &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsyo7wwj5ovvulab8pl0y.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsyo7wwj5ovvulab8pl0y.gif" alt="GIF of an animated star on a black background"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>monolith</category>
      <category>opensource</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
