A few weeks ago I had a small task: build an API that takes a piece of text like a customer review, sends it to an AI model, and returns whether it's positive, negative, or neutral, with a one-line summary.
If you'd asked me how I'd build it, I'd have said "Express, probably. Or Flask." That's my comfort zone. Instead I tried something I'd never touched: Ballerina, an open-source language created by WSO2 for building APIs and connecting services.
My first reaction to the syntax was honestly "what is this?" It looks like Java and Python had a child. But by the end of the afternoon, I had a working service, and somewhere in the middle of building it, I understood why this language exists. Here's the part that stuck with me.
The boring problem Ballerina is built for
You only notice this after building a few backend services: most of your code isn't your actual logic. It's plumbing. You receive a request, pull out the JSON, check it's the right shape, call some other service, handle it failing, reshape the response, and send it back. The interesting part "figure out the sentiment" is two lines. The rest is wiring.
In most languages that wiring is bolted on with libraries. Ballerina's bet is to build the networking into the language itself. Three things showed me what that actually means.
1. The endpoint is the function
In Express you write app.post('/analyze', handler) - the route and the handler are two things you connect. In Ballerina they're one thing:
resource function post analyze(AnalyzeRequest req) returns AnalysisResult|error {
// ...
}
The word post is the HTTP verb. The name analyze is the path. So this line is POST /analyze. No separate routing,the shape of my code is the shape of my API. And that AnalyzeRequest req? Ballerina automatically pours the incoming JSON into a typed record, so by the time my code runs I already have a clean req.text. No manual parsing.
2.One little arrow that changes how you think
To call the AI, I make this request:
groqClient->post("/chat/completions", requestBody, headers);
Look at the arrow - ->, not a dot. In Ballerina, -> is reserved for network calls. Local stuff uses a normal dot; anything that leaves your computer uses the arrow.
At first I thought it was a quirk. Then it clicked: a network call is fundamentally different from a local one ,it's slow, it can time out, the other side can be down. Ballerina makes that danger visible right in the syntax, so you can't forget you're crossing a boundary. Now plain dots everywhere feel like they're hiding something.
3. Errors you can't accidentally ignore
My function returns AnalysisResult|error - that bar means "either a result or an error." Errors aren't thrown off to the side; they're a normal return value, sitting right there in the type.
And the calls have a little check in front:
GroqResponse groqResponse = check groqClient->post(...);
check means: do this, but if it comes back as an error, stop here and pass that error up. It's the whole try/catch dance in five letters (if you know Rust's ? or Go's err, it's that idea). My code reads top-to-bottom as the happy path, and check quietly handles the failures without cluttering everything.
So what's it actually for?
Here's how I'd explain Ballerina to a friend now: it's for the glue. The services whose whole job is to sit between other things calling APIs and databases, reshaping data, passing it along. Exactly the kind of work that keeps growing as we wire apps up to external APIs and, more and more, to AI models.
My little feedback analyzer is a tiny version of a very real pattern: putting a clean, typed API in front of a language model so the messy outside world only ever sees something tidy. Ballerina made that feel natural instead of fiddly.
The honest beginner take
It wasn't all smooth,the syntax took a beat, and I leaned on the docs. There's lots I haven't touched yet: a real database instead of in-memory storage, tests, retries. But the thing that stayed with me is that I spent the afternoon thinking about what I wanted to build, not how to wire it up. For a language built for connecting things, that's the best compliment I can give it.
If you usually build APIs the "import a framework and stitch it together" way, Ballerina is worth an afternoon of your curiosity.
The full project is on my GitHub:
GitHub Repo
if you'd like to poke around the code.
Top comments (0)