Cloud Native 20 min read

Ballerina Integration Tutorial: Building a Twitter‑Enabled Microservice with Circuit Breaker and Kubernetes Deployment

This tutorial demonstrates how to create a Ballerina‑based microservice that receives a POST payload, posts it to Twitter, uses a circuit breaker for an unreliable external quote service, and deploys the service with observability to Kubernetes, illustrating integration, code generation, and cloud‑native deployment.

Architects Research Society
Architects Research Society
Architects Research Society
Ballerina Integration Tutorial: Building a Twitter‑Enabled Microservice with Circuit Breaker and Kubernetes Deployment

Key Points

Ballerina is a new programming language and platform designed for resilient services that integrate and orchestrate distributed endpoints.

It provides compile‑time abstractions for distributed system primitives, enabling type‑safe data transformation and automatic generation of deployment artifacts such as Docker and Kubernetes API gateways.

The language includes keywords for integration concepts like network endpoints, services, streams, SQL, tables, JSON, and XML, allowing tools to generate sequence diagrams from any Ballerina code.

Setup

Install Ballerina, add it to your PATH, and use Visual Studio Code with the Ballerina language server extension for rich IntelliSense and debugging. Install curl for testing, and ensure Docker and Kubernetes (kubectl) are available.

Create a twitter.toml file containing your Twitter API credentials (clientId, clientSecret, accessToken, accessTokenSecret).

Part 1 – Create a Service with a POST Resource

Create homer.bal with the following code:

// The `http` package which is part of the standard library
import ballerina/http;

@http:ServiceConfig {
    basePath: "/"
}
service<http:Service> hello bind {port:9090} {
    @http:ResourceConfig {
        path: "/",
        methods: ["POST"]
    }
    hi (endpoint caller, http:Request request) {
        // Extract the payload from the incoming request.
        string payload = check request.getTextPayload();
        http:Response res;
        res.setPayload("Hello "+payload+"!\n");
        _ = caller->respond(res);
    }
}

Run the service with ballerina run homer.bal and test it using curl -X POST -d "Ballerina" localhost:9090 , which returns Hello Ballerina! .

Part 2 – Send a Tweet via the Twitter Connector

Search and pull the Twitter connector package:

$ ballerina search twitter
$ ballerina pull wso2/twitter

Update homer.bal to import the connector and read credentials from the TOML file:

import ballerina/http;
import wso2/twitter;
import ballerina/config;

endpoint twitter:Client tweeter {
    clientId: config:getAsString("clientId"),
    clientSecret: config:getAsString("clientSecret"),
    accessToken: config:getAsString("accessToken"),
    accessTokenSecret: config:getAsString("accessTokenSecret"),
    clientConfig: {}
};

@http:ServiceConfig {basePath: "/"}
service<http:Service> hello bind {port:9090} {
    @http:ResourceConfig {path: "/", methods: ["POST"]}
    hi (endpoint caller, http:Request request) {
        string payload = check request.getTextPayload();
        if (!payload.contains("#ballerina")) {payload = payload + " #ballerina";}
        twitter:Status st = check tweeter->tweet(payload);
        json myJson = {text: payload, id: st.id, agent: "ballerina"};
        http:Response res;
        res.setPayload(myJson);
        _ = caller->respond(res);
    }
}

Run the updated service with the config file: ballerina run --config twitter.toml homer.bal . Posting to the service now returns a JSON object containing the tweet text, ID, and agent.

Part 3 – Add a Circuit Breaker for an Unreliable Quote Service

Introduce an external HTTP client with a circuit breaker configuration and modify the resource to fetch a quote before tweeting:

import ballerina/http;
import wso2/twitter;
import ballerina/config;

endpoint http:Client homer {
    url: "http://www.simpsonquotes.xyz",
    circuitBreaker: {
        failureThreshold: 0,
        resetTimeMillis: 3000,
        statusCodes: [500, 501, 502]
    },
    timeoutMillis: 500
};

endpoint twitter:Client tweeter { /* same as before */ };

@http:ServiceConfig {basePath: "/"}
service<http:Service> hello bind {port:9090} {
    @http:ResourceConfig {path: "/", methods: ["POST"]}
    hi (endpoint caller, http:Request request) {
        http:Response res;
        var v = homer->get("/quote");
        match v {
            http:Response hResp => {
                string payload = check hResp.getTextPayload();
                if (!payload.contains("#ballerina")) {payload = payload + " #ballerina";}
                twitter:Status st = check tweeter->tweet(payload);
                json myJson = {text: payload, id: st.id, agent: "ballerina"};
                res.setPayload(myJson);
            }
            error err => {
                res.setPayload("Circuit is open. Invoking default behavior.");
            }
        }
        _ = caller->respond(res);
    }
}

Repeated curl -X POST localhost:9090 calls demonstrate the circuit breaker opening after failures and closing after the reset time.

Part 4 – Deploy the Service with Observability to Kubernetes

Add the Kubernetes package and annotate the listener and service to generate Docker images, Kubernetes Deployment, Service, and ConfigMap artifacts:

import ballerina/http;
import wso2/twitter;
import ballerina/config;
import ballerinax/kubernetes;

endpoint twitter:Client tw { /* credentials */ };

@kubernetes:Service {serviceType: "NodePort", name: "ballerina-demo"}
endpoint http:Listener listener {port: 9090};

@kubernetes:Deployment {image: "demo/ballerina-demo", name: "ballerina-demo"}
@kubernetes:ConfigMap {ballerinaConf: "twitter.toml"}
@http:ServiceConfig {basePath: "/"}
service<http:Service> hello bind listener {
    @http:ResourceConfig {path: "/", methods: ["POST"]}
    hi (endpoint caller, http:Request request) {
        // existing resource logic
    }
}

Build with ballerina build demo.bal , which creates a kubernetes/ directory containing Dockerfile, Deployment, Service, and ConfigMap YAML files. Deploy to a cluster using kubectl apply -f kubernetes/ , then invoke the service via the exposed NodePort.

Additional Ballerina Features

Strongly typed type system with primitives such as json, xml, tables, unions, and tuples.

Workers provide lightweight concurrency; the -> arrow syntax denotes network calls.

Sequence diagrams can be generated automatically from annotated source code.

Testerina offers a unit‑testing framework for services.

IntegrationMicroservicesKubernetescircuitbreakertutorialBallerina
Architects Research Society
Written by

Architects Research Society

A daily treasure trove for architects, expanding your view and depth. We share enterprise, business, application, data, technology, and security architecture, discuss frameworks, planning, governance, standards, and implementation, and explore emerging styles such as microservices, event‑driven, micro‑frontend, big data, data warehousing, IoT, and AI architecture.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.