DEV Community

Arkeshkar Prashanthkumar
Arkeshkar Prashanthkumar

Posted on

Building a Real-Time Medicine Finder on WSO2 Choreo: What a Developer Platform Actually Solves

The problem: one prescription, five pharmacies

If you have ever walked from pharmacy to pharmacy with a prescription, asking "do you have this?", you know the problem. Stock information exists, but it sits inside each shop, invisible to the person who needs it.

So I built MediFind: a web app where anyone can search for a medicine and see which nearby pharmacies have it in stock, while pharmacy staff keep that stock up to date in real time.

I built it entirely on WSO2 Choreo. I wanted to answer one question: how far can a single platform take a solo developer, from an empty GitHub repo to a secured, multi-service, observable application?

This post is not a feature tour. It is the six problems Choreo solved for me, plus the places where it surprised me.

TL;DR: 8 components, 2 environments, OAuth-secured APIs, role-based access, WebSocket live updates, scheduled jobs and monitoring. Zero Dockerfiles, zero Kubernetes manifests, zero CI scripts.

What Choreo is, in plain words

Choreo is WSO2's internal developer platform, recently rebranded as the WSO2 Developer Platform. You connect a Git repository, and Choreo builds, deploys, secures, connects and monitors what is inside it.

The problem it targets is simple to state. Modern apps are not one program anymore. They are services, APIs, front ends, background jobs and third-party integrations, and each one needs a build pipeline, a runtime, security, configuration and monitoring. A small team usually ends up spending more time on that plumbing than on the product.

Choreo's bet is that the plumbing should be a platform feature, not a project of its own. My experience building MediFind mostly confirmed that bet.

What I built

MediFind has three faces: a public search page, a staff dashboard that updates live, and automation that runs with nobody touching it. Under the hood, that is eight Choreo components living in one GitHub repository.

People and outside systems enter at the top, and everything inside the dashed box is built, deployed and secured by Choreo. The Inventory Service is the core API, and the scheduled task reaches the Ballerina notification service through a Choreo Connection.

Problem 1: Shipping services without a DevOps team

I wrote zero Dockerfiles, zero Kubernetes manifests and zero CI scripts for eight deployed components. Each component is just a folder in one GitHub monorepo, and Choreo's buildpacks (Node.js, React, Ballerina) turn that folder into a running container.

The only platform file I wrote per service is a small .choreo/component.yaml. It tells Choreo the port, the API definition, and which configuration values to ask for:

schemaVersion: 1.2
endpoints:
  - name: inventory-api
    service:
      basePath: /
      port: 8080
    type: REST
    networkVisibilities: [Public, Organization]
    schemaFilePath: openapi.yaml
configurations:
  env:
    - name: DATABASE_URL
      valueFrom:
        configForm:
          displayName: Database URL
          type: secret
          required: true
Enter fullscreen mode Exit fullscreen mode

That configForm block is quietly powerful. At deploy time, Choreo shows a form asking for the database URL and stores it as a secret, so credentials never touch the repository.

Three more things removed whole categories of work:

  • Environments and promotion. Every component gets Development and Production. I tested on Development, then clicked Promote to move the exact same build to Production, with a different database URL per environment.
  • Auto Deploy on Build. One toggle, and every git push builds and deploys to Development. That is CI/CD without writing a pipeline.
  • Scale to Zero. Idle services sleep and wake on the next request, which kept my experiment within the free tier.

Problem 2: Securing and managing APIs

This is where WSO2's long history in API management shows. Every endpoint I deployed went behind the Choreo gateway, secured with OAuth2 by default. I did not write a single line of authentication code in my services.

From there, I tuned security rather than built it:

  • Per-resource security. Public search and health checks have security switched off; everything else needs a token.
  • Permissions (scopes). I created a stock:write permission and attached it only to the write operations, such as POST /stock/adjust.
  • Rate limiting and CORS, set per environment from one settings pane.
  • Lifecycle and the Developer Portal. Publishing the API listed it in a portal where a consumer creates an app, subscribes, and generates credentials.

The moment it clicked for me was a five-line PowerShell test against the production URL:

Request Result
No token 401 Unauthorized
Valid token, search 200 OK
Token without stock:write, update stock 403 Forbidden
Hammering the search endpoint 429 Too Many Requests

Four status codes, and none of them came from my code.

Problem 3: Login and roles in a single-page app

Authentication in a React app is usually where weekends disappear: OIDC libraries, token storage, refresh logic, and the constant worry about tokens leaking to the browser. Choreo's Managed Authentication removed all of it.

It follows the backend-for-frontend pattern, so OAuth tokens never reach browser JavaScript. My login button is literally a redirect:

<button onClick={() => { window.location.href = '/auth/login'; }}>
  Pharmacy Login
</button>
Enter fullscreen mode Exit fullscreen mode

Calling my secured API from the browser needed no token handling either. The app calls a relative path, and the session cookie does the rest:

const res = await fetch(
  `/choreo-apis/medifind/inventory-service/v1.0/pharmacies/${id}/stock`
);
Enter fullscreen mode Exit fullscreen mode

For authorization, I used Choreo's built-in identity provider. I uploaded test users from a CSV file, created a pharmacy_staff role holding the stock:write permission, and mapped it to a PharmacyStaff group.

A staff user can now update stock from the dashboard, while a viewer gets a clean "no permission" message. The rule lives in the platform, not in an if statement in my code.

Problem 4: Services finding and calling each other

In most projects, service-to-service calls mean hard-coded URLs, copied API keys and a different setup per environment. Choreo replaces that with Connections.

From a component, I open Connections, browse the internal Marketplace of services in my organization, and pick the one I need. Choreo then injects the right URL and credentials for each environment. My scheduled task finds its connection with three lines of code and never knows whether it is running in Development or Production.

Two details made the architecture cleaner:

  • Network visibility. My Ballerina notification service is visible to the Project only. Nothing outside MediFind can reach it, by configuration rather than firewall rules.
  • API Proxy. To show drug information next to search results, I put the free U.S. FDA drug label API behind a Choreo API proxy. My web app calls my own gateway, which adds rate limiting, CORS and a timeout in front of a third-party API I do not control. An optional mediation policy can even inject the API key at the gateway, so it never appears in front-end code.

Problem 5: Background jobs, real-time updates and more than one language

Real products need more than request-response APIs. MediFind needed jobs, events and live updates, and each mapped to a Choreo component type:

Need Choreo component What it does in MediFind
Daily low-stock alerts Scheduled Task Runs at 8:00 AM, finds low stock, and asks the notification service to email each pharmacy
Bulk stock upload Manual Task Imports a pharmacy's stock list from a CSV file, with validation and a dry-run mode
Sending emails Ballerina service Builds the HTML alert and calls the Brevo email API
Flexible search GraphQL service Lets clients ask for exactly the fields they need in one request
Live dashboard WebSocket service Pushes stock changes to every open dashboard within seconds
Supplier deliveries Signed webhook endpoint Adds delivered stock automatically, verified with an HMAC signature

Writing the notification service in Ballerina, WSO2's open-source integration language, was a highlight. Calling an external HTTP API and turning JSON into a typed record took a few lines, and its configurable variables appeared automatically as a secure form in Choreo:

configurable string brevoApiKey = ?;
configurable string senderEmail = ?;
Enter fullscreen mode Exit fullscreen mode

Choreo also took each API's definition seriously: OpenAPI for REST, a schema file for GraphQL, and AsyncAPI for the WebSocket service. Each published API shows up properly documented in the Developer Portal.

Problem 6: Knowing what is happening in production

With eight components, "is it working?" stops being a simple question. Choreo answers it without adding a logging or metrics stack:

  • Logs from every component, searchable in one place. I could find the exact line where a supplier delivery was applied, or where the scheduled task sent its emails.
  • Metrics for request count, latency and errors per service.
  • Alerts on latency and error rate, sent to my email.
  • Health checks that restart a service that stops responding.
  • Insights dashboards showing API usage across the whole organization.

None of this required extra code. A one-line request logger in my Express app was enough to make the log view genuinely useful.

What I would tell a beginner

Choreo is not magic, and a few things cost me time. Knowing them up front will save you some:

  1. The console moves faster than tutorials. Settings I expected under one menu had moved. Security and permissions now live under Endpoint Configurations on the Deploy page, and CORS and rate limiting sit on each environment card. When a guide does not match your screen, trust the current WSO2 docs.
  2. Managed databases are a paid feature. I used a free external PostgreSQL database (Neon) instead and passed its URL as a secret. Connecting external services is a first-class Choreo pattern, so nothing was lost.
  3. Check for deprecations. The dedicated Webhook and Test Runner components are marked deprecated in the latest docs. I built the webhook as an HMAC-signed endpoint on my REST service, and used Ballerina unit tests plus a smoke-test script instead.
  4. Redeploy after changing connections or permissions. Several "it doesn't work" moments were fixed by a redeploy.
  5. Mind the free tier. Plan your components before you create them, and let Scale to Zero do its job.
  6. Never commit secrets. Use configForm secrets in component.yaml, keep .env files in .gitignore, and check your Git history before you share the repository.

The verdict

Choreo let one developer ship what would normally need a small platform team: eight components, two environments, OAuth-secured APIs, role-based access, real-time updates, scheduled jobs and monitoring.

Its real value is not any single feature. It is that security, configuration, connections and observability are the default, so the code I wrote was almost entirely product code.

If you are a student, a startup, or a small team that keeps postponing "proper" API security and CI/CD, Choreo is worth an afternoon. Start with one REST service and a web app, then add components as your product needs them.

💻 Source code:

💊 MediFind: Medicine Availability Platform on WSO2 Choreo

MediFind helps people find which nearby pharmacies have a medicine in stock, and helps pharmacies manage stock, receive supplier deliveries automatically, and get low-stock alerts.

Live app: [your web app URL] Demo video: [YouTube/Drive link]

Architecture

flowchart LR
    U[Public user] --> W[React Web App<br/>Managed Auth]
    S[Pharmacy staff] --> W
    W -->|Connection| I[Inventory Service<br/>Node.js REST]
    W -->|Connection| F[openFDA API Proxy]
    W -->|WebSocket| L[Live Stock Service<br/>Node.js WS]
    SUP[Supplier system] -->|HMAC-signed webhook| I
    G[Search Service<br/>Node.js GraphQL] --> DB[(PostgreSQL<br/>Neon)]
    I --> DB
    L --> DB
    T[Low-Stock Report<br/>Scheduled Task] --> DB
    T -->|Connection| N[Notification Service<br/>Ballerina]
    N --> B[Brevo Email API]
    C[CSV Import<br/>Manual Task] --> DB
    F --> FDA[U.S. FDA API]
Loading

WSO2 Choreo features used

Area Features
Component types REST service, GraphQL service, WebSocket service, Ballerina service, API Proxy, Web Application, Scheduled Task, Manual Task
API management OAuth2, per-resource security, permissions (scopes), CORS, rate limiting, resiliency, mediation
…

Have you built something on Choreo or the WSO2 Developer Platform? What worked for you, and what tripped you up? Let me know in the comments! 👇

Top comments (0)