GoLang to Kotlin Migration for a Medical Device Integration Plugin

A Holter cardiac monitoring device connected to a clinician's laptop running the browser-based clinical application
  • 3 Device adapters migrated
  • 3 Milestones, formally accepted
  • 70%+ Baseline coverage per module
  • 30 days Validated parallel run

Introduction

A European medtech company that develops clinical-grade cardiac and physiological monitoring solutions relied on a locally installed plugin, written in GoLang, to bridge medical hardware and its browser-based clinical web applications. The plugin handles device communication, local data caching and secure upload to cloud storage.

The client decided to move the plugin to Kotlin without interrupting the clinical workflows that depend on it. The objective was clear: migrate three device adapters and the common plugin infrastructure to a production-ready Kotlin Multiplatform codebase, preserving identical business logic, data contracts and clinical behavior, and retire the Go service only once parity was proven.

The Challenge

Migrating a Live Clinical Device Bridge Without Disruption

  • Preserving Clinical Behavior Across a Language Change

    The plugin sits between medical hardware and clinical applications, so the migration could not change what the software does. Challenges included:

    • Reproducing business logic, data contracts and clinical behavior exactly, in a different language
    • Translating Go’s concurrency model, goroutines and channels, into Kotlin without changing runtime behavior
    • Keeping the WebSocket contract with the browser application and the cloud storage interface unchanged
    • Making sure device data cached locally is neither lost nor altered before upload
    • Avoiding a big-bang cutover on software that clinicians depend on
  • Three Devices, Three Integration Paths

    Each supported device talks to the plugin differently, and each brought its own constraints. Key obstacles:

    • A Holter recorder integrated over the USB mass storage protocol (medium-high complexity)
    • A high-fidelity ECG monitor reachable only through a third-party, Windows-only DLL, requiring JNI bindings from Kotlin and a DLL the client neither owns nor modifies (high complexity)
    • A blood pressure monitor with no emulator, so validation depended on client-supplied hardware (very high complexity)
    • Supporting Windows, macOS and Linux for the common plugin while accepting a Windows-only constraint for the DLL adapter
  • Proving Equivalence Before Retiring the Go Service

    Retiring working software is only safe when equivalence is demonstrated. Challenges included:

    • Establishing a baseline: a dependency map and test coverage for the Go code, with a target of at least 70% per device module
    • Comparing Go and Kotlin outputs on the same de-identified clinical datasets against acceptance thresholds agreed for each device’s clinical algorithms
    • Validating without patient testing, using emulators, mock cloud services and datasets
    • Coordinating dependencies on client inputs: repository access, emulators, protocol specifications, hardware and a technical point of contact

Our Solution: A Staged, Parity-Proven Migration Framework

Nalashaa implemented a client-aligned migration approach built on the Strangler Fig pattern: the Go and Kotlin services run in parallel, device by device, and the Go service is retired only after the Kotlin version is fully validated.

The solution allowed the client to:

  • Keep the existing Go plugin running while each Kotlin adapter was built and proven
  • Move device by device, following one repeatable path: Identify, Translate, Integrate, Validate, Retire
  • Leave the browser application and the cloud storage service untouched
  • Retire Go only after a 30-day validated parallel run and formal sign-off
  • Address audit, conversion, validation and cutover in a single, cohesive engagement

This approach ensured the migration progressed at a pace fully controlled by the client. We delivered the migration as three tasks, each closed by a milestone acceptance review.

  1. Foundation & Common Plugin Infrastructure

    SOLUTION HIGHLIGHTS

    • Audited and inventoried the Go repositories, producing a dependency map and a baseline test coverage report
    • Initialized a Kotlin Multiplatform monorepo with a Gradle version catalog
    • Built an idiomatic Go-to-Kotlin conversion framework (rules below)
    • Built an automated parity test harness that feeds the same dataset to the Go service and the Kotlin module and diffs the outputs
    • Migrated the common plugin functionality: the WebSocket layer between browser and plugin, persistent local caching before upload, secure cloud upload, and device listing and command dispatch

    TECHNICAL ENHANCEMENTS

    • Ktor, with WebSocket support, replacing Go HTTP handlers
    • Coroutines and Flow replacing goroutines and channels
    • Koin for dependency injection
    • Sealed classes for structured error handling
    Conversion rules applied throughout:
    GO CONSTRUCTKOTLIN EQUIVALENT
    StructsData classes
    GoroutinesCoroutines
    ChannelsKotlin Flow
    InterfacesInterfaces
    Error handlingSealed classes
    HTTP handlersKtor route handlers
    Go dependenciesKotlin libraries
  2. Mass Storage and DLL/JNI Device Adapters

    SOLUTION HIGHLIGHTS

    • Migrated the Holter recorder adapter, which communicates over the USB mass storage protocol, and validated it against an emulator
    • Built the high-fidelity ECG adapter in Kotlin with JNI bindings to the vendor’s third-party DLL, delivered as a Windows-only component
    • Used a DLL emulator that replicates the vendor DLL’s behaviour, so the adapter could be tested without the physical device
    • Followed Identify, Translate, Integrate, Validate, Retire for each device, moving device traffic from the Go service to the Kotlin service
    • Produced a parity report for each adapter and a parallel operation validation report

    TECHNICAL ENHANCEMENTS

    • Serial protocol handling for retrieving device serial numbers and settings
    • The Windows-only constraint contained within the ECG adapter, leaving the common plugin cross-platform

    Migration rule in practice: each adapter is retired from Go only once its Kotlin counterpart matches the Go output on the same dataset within the thresholds agreed for that device.

    Outcome: Both adapters were shown to match their Go predecessors on the same datasets and emulators, giving the client evidence rather than assurance.

  3. Hardware-Interface Adapter, UAT & Go Retirement

    SOLUTION HIGHLIGHTS

    • Migrated the blood pressure monitor adapter, using client-supplied hardware for hardware-in-the-loop testing because no emulator exists
    • Ran end-to-end testing across all three devices: development testing, technical validation, code comparison with the legacy plugin and QA output comparison on emulators, followed by the client’s own user acceptance testing in their environment
    • Ran a 30-day validated parallel run, with the Go and Kotlin services operating on the same database
    • Retired the Go module on completion of the run and client sign-off
    • Delivered release readiness documentation and a deployment handover package

    BUSINESS ENABLEMENT

    • A single Kotlin Multiplatform codebase that the client’s engineers can extend
    • The common plugin and two of the three adapters available on Windows, macOS and Linux
    • A repeatable adapter pattern for future devices, with knowledge transfer at handover
    • Formal offboarding, with documentation and access revocation at close

Together, the three tasks moved the plugin from Go to Kotlin one validated step at a time (Figure 1).

Figure 1: Staged migration flow, from Go-only to Kotlin-only, with the per-device loop and three milestones

Architecture & Governance

Figure 2: Local plugin architecture on Kotlin Multiplatform, with the parity and validation layer

From the client’s standpoint, the architecture delivered (Figure 2):

  • The plugin stayed a locally installed bridge, with no cloud or container hosting introduced

  • Interfaces to the browser application and the cloud storage endpoint left unchanged

  • One adapter per device, so each device’s protocol, emulator and platform constraints stay isolated

  • A parity harness and a parallel run that made every cutover decision evidence-based

  • Coexistence: Go and Kotlin running side by side on the same database until sign-off

This architecture enabled migration without sacrificing reliability.

Technology and Controls

CORE TECHNOLOGIES

  • Kotlin (Kotlin Multiplatform) with a Gradle version catalog
  • Ktor for HTTP and WebSocket communication
  • Kotlin Coroutines and Flow for concurrency and streaming
  • Koin for dependency injection
  • JNI bindings to a third-party DLL (Windows-only)
  • USB mass storage and serial protocol handling
  • GitHub, with Jira or GitHub Issues for task tracking

OPERATIONAL CONTROLS

  • Entry gate: Go dependency map and baseline test coverage of at least 70% per device module
  • Automated parity comparison against thresholds agreed for each device’s clinical algorithms
  • Validation on de-identified datasets, emulators and mock services, with no patient testing
  • Weekly status calls, ad-hoc technical calls and formal milestone acceptance meetings
  • Written change control: any scope change handled through a formal change order
  • Formal offboarding with knowledge transfer and access revocation

Business Impact & ROI

AREA IMPACT
Clinical ContinuityGo service stayed live until Kotlin parity was proven, so device workflows were not interrupted
Risk MitigationAutomated parity harness and a 30-day parallel run replaced assumption with evidence
MaintainabilityOne modern Kotlin Multiplatform codebase with idiomatic patterns, replacing the Go plugin
Platform ReachCommon plugin and two of three adapters on Windows, macOS and Linux; the DLL constraint contained
Delivery PredictabilityFixed scope, three milestones, an explicit out-of-scope list and formal change control
Future ReadinessSelf-update and diagnostics deferred by design, ready for a later phase on the new base

Quantifiable Outcomes

Measured against the engagement’s own yardsticks:

  • 3

    Device adapters migrated and validated against their Go predecessors

  • 3

    Milestones, each closed by a formal acceptance review

  • 70%+

    Go baseline test coverage per device module, set as the entry gate

  • 30 days

    Validated parallel run completed before the Go module was retired

  • Retired

    Go module retirement confirmed, with the browser application and cloud endpoint left unchanged

Strategic Value Delivered

This initiative demonstrates how a production device-integration layer can change language safely, without a big-bang rewrite.

By combining a Strangler Fig rollout, an automated parity harness and device-by-device adapter migration, the client now benefits from:

  1. A modern, maintainable Kotlin Multiplatform codebase
  2. Proven clinical equivalence with the legacy plugin
  3. Cross-platform reach wherever the devices allow it
  4. A repeatable pattern for migrating and adding adapters
  5. Lower long-term technical risk

Looking Ahead

With the Kotlin foundation in place, the organization is now positioned to:

  • Add self-update capability, deferred to a later phase
  • Add diagnostic and telemetry functionality, likewise deferred
  • Onboard new device adapters using the established pattern
  • Extend platform support as its device portfolio evolves
  • Modernize incrementally without business disruption

Migrate without disrupting. Validate before you retire. Deliver without compromise.

Let’s Talk

Talk to a Healthcare Engineering Expert

Field will not be visible to web visitor

Cookies help us deliver our services. By using our services, you agree to our use of cookies Privacy Policy. I Accept It!