<?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: Chiran keshawa Weerasekara</title>
    <description>The latest articles on DEV Community by Chiran keshawa Weerasekara (@chirankebeep).</description>
    <link>https://dev.to/chirankebeep</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4245142%2F0505e83e-d194-4827-85ce-c765dcc2ae6f.jpg</url>
      <title>DEV Community: Chiran keshawa Weerasekara</title>
      <link>https://dev.to/chirankebeep</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/chirankebeep"/>
    <language>en</language>
    <item>
      <title>Building StatusWatch: A Multi-Service Status Checker with Ballerina</title>
      <dc:creator>Chiran keshawa Weerasekara</dc:creator>
      <pubDate>Sat, 14 Nov 2026 23:28:12 +0000</pubDate>
      <link>https://dev.to/chirankebeep/building-statuswatch-a-multi-service-status-checker-with-ballerina-26nf</link>
      <guid>https://dev.to/chirankebeep/building-statuswatch-a-multi-service-status-checker-with-ballerina-26nf</guid>
      <description>&lt;h2&gt;
  
  
  Building StatusWatch: A Multi-Service Status Checker with Ballerina
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;By Chiran Keshawa Weerasekara&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Have you ever tried to push code to GitHub or install an npm package, only to find that something isn't working? When that happens, one of the first things I usually wonder is whether the problem is in my code or whether the service itself is experiencing an issue.&lt;/p&gt;

&lt;p&gt;To find out, I would normally open separate browser tabs for GitHub, Cloudflare, and npm and check their status pages one by one. It works, but doing the same thing repeatedly can become a little frustrating.&lt;/p&gt;

&lt;p&gt;I decided to build a small project to make this easier. I called it &lt;strong&gt;StatusWatch&lt;/strong&gt;. It is a backend service built with &lt;strong&gt;Ballerina&lt;/strong&gt; that checks the current status of GitHub, Cloudflare, and the npm Registry and combines the results into a single response.&lt;/p&gt;

&lt;p&gt;The main idea was simple: instead of checking three services separately, I wanted to get all their status information in one place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Chose Ballerina
&lt;/h2&gt;

&lt;p&gt;For this project, I wanted to try something different from the languages and frameworks I normally use. I chose Ballerina, an open-source programming language developed by WSO2.&lt;/p&gt;

&lt;p&gt;Ballerina is designed to make working with APIs and network services easier. Since this project mainly involves communicating with external APIs, it felt like a good opportunity to explore the language and understand how it handles these kinds of tasks.&lt;/p&gt;

&lt;p&gt;One feature that interested me was &lt;strong&gt;Ballerina workers&lt;/strong&gt;. They allow independent tasks to run concurrently, which was useful because I didn't want the application to wait for one status check to finish before starting the next one.&lt;/p&gt;

&lt;h2&gt;
  
  
  How StatusWatch Works
&lt;/h2&gt;

&lt;p&gt;The application has a single endpoint:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GET /health/overview&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;When this endpoint is called, StatusWatch starts three checks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub Status API&lt;/li&gt;
&lt;li&gt;Cloudflare Status API&lt;/li&gt;
&lt;li&gt;npm Registry Status API&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rather than calling them one after another, I used Ballerina workers to start the requests concurrently. The application then waits for the results and combines them into one response.&lt;/p&gt;

&lt;p&gt;For example, if GitHub takes 300 milliseconds, Cloudflare takes 1,100 milliseconds, and npm takes 500 milliseconds, checking them sequentially would take roughly 2 seconds based on those response times. Running them concurrently means the application can finish much closer to the time taken by the slowest request.&lt;/p&gt;

&lt;p&gt;This approach follows a pattern often called &lt;strong&gt;Scatter-Gather&lt;/strong&gt;. In simple terms, the application sends requests to multiple services and gathers their responses into one result.&lt;/p&gt;

&lt;p&gt;Here is a small part of the implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;worker wGithub returns ServiceHealth {
    return fetchStatus(githubClient, "GitHub");
}

worker wCloudflare returns ServiceHealth {
    return fetchStatus(cloudflareClient, "Cloudflare");
}

worker wNpm returns ServiceHealth {
    return fetchStatus(npmClient, "npm Registry");
}

ServiceHealth gh = wait wGithub;
ServiceHealth cf = wait wCloudflare;
ServiceHealth npm = wait wNpm;
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F57ft1jemitjcs0t5264m.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F57ft1jemitjcs0t5264m.png" alt="Ballerina workers implementation in VS Code" width="777" height="513"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once all three checks are complete, their results are combined into a single system overview.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling Different Service Responses
&lt;/h2&gt;

&lt;p&gt;Another part of the project was handling the different responses returned by the services.&lt;/p&gt;

&lt;p&gt;Status APIs can report different conditions, such as operational, minor issues, major issues, or critical incidents. I added a small mapping function to convert these responses into a consistent format:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;OPERATIONAL&lt;/code&gt; – The service is working normally.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DEGRADED&lt;/code&gt; – The service is experiencing some problems.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;OUTAGE&lt;/code&gt; – The service has reported a major issue.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;UNREACHABLE&lt;/code&gt; – The application could not retrieve the service status.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also wanted to make sure that one failed request would not affect the entire application. For example, if Cloudflare does not respond, StatusWatch can still return the results from GitHub and npm.&lt;/p&gt;

&lt;p&gt;After collecting the results, the application calculates an overall status, such as &lt;code&gt;ALL_OPERATIONAL&lt;/code&gt;, &lt;code&gt;PARTIAL_OUTAGE&lt;/code&gt;, or &lt;code&gt;MAJOR_OUTAGE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This makes the response easier to understand without having to inspect each service separately.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing It with Real Services
&lt;/h2&gt;

&lt;p&gt;After completing the main functionality, I started the Ballerina service locally and tested the endpoint using curl:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:9090/health/overview
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During one of my live tests on November 13, 2026, I received a partial outage response. GitHub and Cloudflare were reported as degraded, while the npm Registry was operational.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffxw3ovlz1au07aciyye4.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffxw3ovlz1au07aciyye4.png" alt="Cloudflare status page showing active incidents" width="800" height="658"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I checked the official status pages to compare the results and found incident notices matching the issues reported by my application.&lt;/p&gt;

&lt;p&gt;Seeing the application identify different service conditions during a real test was one of the most satisfying parts of building this project. It also gave me a chance to see how the application behaved when not every external service was operating normally.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing and GitHub Actions
&lt;/h2&gt;

&lt;p&gt;I also added unit tests in &lt;code&gt;tests/service_test.bal&lt;/code&gt; to check the application's endpoints and status-mapping logic.&lt;/p&gt;

&lt;p&gt;The tests can be executed using:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;To make the project easier to maintain, I set up a GitHub Actions workflow in &lt;code&gt;.github/workflows/build.yml&lt;/code&gt;. It runs the test suite using a Ballerina container whenever I push changes to the repository.&lt;/p&gt;

&lt;p&gt;This helped me make testing part of the development process instead of relying only on manual testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;Building StatusWatch gave me an opportunity to explore Ballerina through a practical project rather than just reading about its features.&lt;/p&gt;

&lt;p&gt;A few things I learned along the way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Working with APIs:&lt;/strong&gt; I gained more experience connecting to external APIs and processing their responses using Ballerina.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concurrent execution:&lt;/strong&gt; I understood how workers can help reduce waiting time when an application needs information from multiple services.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error handling:&lt;/strong&gt; I learned why external services should be treated as unreliable and why one failed request should not bring down an entire application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing and automation:&lt;/strong&gt; Setting up unit tests and GitHub Actions helped me understand the importance of checking code changes automatically.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also found that Ballerina made it straightforward to work with HTTP requests and JSON responses without needing to depend on many additional libraries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;StatusWatch started as a small idea to avoid opening multiple status pages whenever something went wrong during development. It turned into a useful opportunity to explore Ballerina and understand how it can be used to build API-based services.&lt;/p&gt;

&lt;p&gt;The project is fairly small, but it helped me learn more about concurrent API requests, error handling, and automated testing. More importantly, it gave me a chance to build something practical while exploring a technology I had not used much before.&lt;/p&gt;

&lt;p&gt;You can find the source code, tests, and setup instructions here:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub Repository:&lt;/strong&gt; &lt;a href="https://github.com/chiranke-beep/statuswatch-service" rel="noopener noreferrer"&gt;https://github.com/chiranke-beep/statuswatch-service&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>ballerina</category>
      <category>wso2</category>
      <category>api</category>
      <category>backend</category>
    </item>
  </channel>
</rss>
