Skip to content
ZERO-RISK100% replacement guarantee on every hire.See how we work
Back to all case studies

CASE STUDY ยท FINANCIAL SERVICES

How custom Java packages helped an asset management firm reduce build failures and cut dependency risk.

CLIENT ยท ASSET MANAGEMENT FIRMFINANCIAL SERVICES
  • 87%Dependency-related build failures reduction*
  • 96%Release cycle speed, QA โ†’ Production faster*

01 ยท PROJECT OVERVIEW

When every service solves the same problem twice.

The client runs enterprise financial applications on a Java microservices estate. Each service had grown on its own timeline, with its own dependency versions and its own private copies of logic that half the other services also needed.

Nothing was broken enough to stop the business. But everything was slow enough to cost it. A library upgrade in one service could quietly break another. Shared utilities lived in three places and drifted apart. Engineers spent more of the sprint negotiating with the build than writing features.

Brandsmashers was brought in as an embedded Java developer inside the client's delivery team not to rebuild the platform, but to make the platform safe to change.

WHAT THE CLIENT WAS DEALING WITH
  1. Dependency versions drifting across services with no shared baseline.
  2. Reusable logic copy-pasted between codebases instead of shared.
  3. Upgrades postponed because nobody could predict what they would break.
  4. Build failures that surfaced late in the CI/CD pipeline rather than early.

02 ยท THE CHALLENGE

Upgrading without breaking anything downstream.

The hardest problem on the engagement was deceptively plain: move dependencies forward without disturbing services that already worked.

Newer library versions brought API changes. Those API changes pulled transitive dependencies behind them. And in a microservices estate, a transitive conflict rarely announces itself in the service you just edited it shows up two services over, in an environment where it is expensive to find.

  • PROBLEM 01API drift

    Method signatures and behaviour changed between versions, breaking compiling code silently at runtime.

  • PROBLEM 02Transitive conflicts

    Two libraries pulling incompatible versions of a third, resolved differently per service.

  • PROBLEM 03Duplicate logic

    The same utility maintained separately in multiple services, each with its own bugs.

  • PROBLEM 04Late feedback

    Problems reached CI/CD or QA instead of being caught at analysis time.

The technical debt wasn't in the code anyone was writing. It was in the code nobody wanted to touch.

03 ยท THE PROCESS

Analysis first, then libraries, then a repeatable path to production.

  1. 01
    Mapped the dependency tree before changing a line

    Every upgrade started as an analysis task, not a code task. Our engineer walked the dependency tree service by service, identified where versions conflicted, and flagged which APIs had actually changed behaviour rather than just version numbers.

  2. 02
    Upgraded and reconciled versions across services

    Dependencies were moved to newer, mutually compatible versions. Where an upgrade forced an API change, the affected code was updated in the same pass so the service never sat in a half-migrated state.

  3. 03
    Built custom Java libraries for shared functionality

    Logic that had been duplicated across services was pulled out into purpose-built internal libraries. One implementation, one owner, one place to fix a bug.

  4. 04
    Packaged and published to the internal artifact repository

    Libraries were built into versioned JAR artifacts and published to the client's internal artifact repository, so consuming services could pin a known version.

  5. 05
    Integrated, tested, and validated the full build

    Each package was integrated into consuming services and put through unit and integration testing, with regression testing and full build validation after any dependency change.

  6. 06
    Supported CI/CD and shepherded releases through to Production

    Build failures in the pipeline were triaged and resolved, and services/packages were deployed across QA, UAT, and Production on a controlled, repeatable path.

THE DELIVERY FLOW, END TO END
  1. 1Requirement
  2. 2Java service development
  3. 3Dependency analysis
  4. 4Custom library build
  5. 5Unit testing
  6. 6JAR packaging
  7. 7Artifact repository
  8. 8Service integration
  9. 9CI/CD pipeline
  10. 10QA โ†’ UAT โ†’ Production

04 ยท RESULTS

What changed.

The estate became safe to upgrade. Shared functionality got a single home. And moving a change from a developer's branch to Production stopped being an act of faith.

BEFOREAFTER
Dependency versions drifting service by serviceReconciled, compatible versions across the estate
Reusable logic duplicated in multiple codebasesShared custom libraries with one owner and one version
Upgrades deferred because the blast radius was unknownDependency analysis and regression testing before every change
Build failures surfacing late in CI/CDFailures triaged and resolved as part of the delivery loop
Ad-hoc deployment across environmentsControlled QA โ†’ UAT โ†’ Production release process
  • Lower technical debt

    Dependency-related debt was paid down instead of accumulating quietly.

  • Higher maintainability

    Services became easier to change because their foundations stopped moving underneath them.

  • Genuine reuse

    Custom packages gave the team a way to write something once and use it everywhere.

  • A process, not a heroic effort

    Building, publishing, and deploying packages became a repeatable path any engineer could follow.

05 ยท DELIVERABLES

What we delivered.

  • Microservice developmentOngoing development and enhancement of multiple Java services.
  • Dependency engineeringVersion upgrades, conflict resolution, and compatibility analysis.
  • Custom Java librariesReusable internal packages replacing duplicated logic.
  • Artifact managementJAR builds published to the internal artifact repository.
  • Testing & validationUnit, integration, and regression testing after every change.
  • Release supportCI/CD build support and deployment across QA, UAT, and Production.
TECHNOLOGY STACK
Language / Architecture
JavaMicroservices
Build
Maven / Gradle
Packaging
JAR PackagingArtifact Repository
Delivery
CI/CD
Quality
Unit & Integration Testing
Environments
QAUATProduction

WHY IT WORKED

One engineer, embedded, with ownership.

This wasn't a project handed over a wall. Brandsmashers placed a Java developer inside the client's team through our IT staff augmentation model close enough to the codebase to see where the real friction was, and accountable enough to fix it end to end, from dependency analysis through to a Production deployment.

That's the pattern we see work most often with engineering-heavy clients: hire capability, not headcount, and let it compound. The custom package layer built here keeps paying off every time a new service needs functionality that already exists.

YOUR TURN

Have services that are hard to change safely?

Brandsmashers Tech embeds engineers who untangle dependencies and make shared code safe to reuse.

NEXT CASE STUDY ยท AGENTIC AIFrom ticket queues to resolution: a multi-agent support system for an online marketplace