← back to clients
banking · ongoing

raiffeisen — coreui-deposits

client
Raiffeisenbank Russia
industry
Banking / Financial services
role
Dedicated embedded fullstack engineer
timeline
May 2025 – present, ongoing
team
1 fullstack engineer
status
ongoing · ongoing

Raiffeisen — coreui-deposits — Case Study

Retail-deposits product UI inside Raiffeisenbank Russia's microfrontend platform. React + Vite + TypeScript + Module Federation, integrating Raiffeisen's @fcc/ui design system, OIDC SSO, deployed via Helm to the bank's Kubernetes cluster.

Summary

coreui-deposits is the deposits product surface — the screens through which Raiffeisenbank Russia's customers and staff interact with retail deposit products. Architecturally it's a Vite + React + TypeScript application that builds two ways: a standalone host for direct deployment, and a Module Federation remote that plugs into the bank's broader microfrontend shell at runtime. It talks to core-ui-bff, a Kotlin/Spring Boot service that owns the deposit API surface (deposit catalog, account info, replenishment, early closure, partial withdrawal) and bridges to the bank's underlying retail-account microservice. topsweteam's embedded engineer is an active contributor to both halves.

  • Client: Raiffeisenbank Russia
  • Engagement: 1 dedicated embedded fullstack engineer (topsweteam)
  • Status: Live in production, ongoing
  • Industry: Banking / Financial services

Challenge

The deposits product has to feel like it belongs to the rest of the bank's app — same shell, same identity, same component vocabulary, same release process — while being independent enough that the deposits team can ship without coordinating with every other product team. That's the microfrontend bargain: the bank doesn't have to coordinate releases across product surfaces, but each surface has to fit the platform precisely or it stops being a microfrontend and starts being a fork.

For a one-engineer engagement, the challenge is doing all of that without inventing anything. Every architectural call should match what the platform team has already decided.

Approach

The engagement is embedded inside the bank's frontend platform team. Code review, conventions, and release cadence all live inside Raiffeisen's existing process. The architectural choices — Vite, React 18, Module Federation, @fcc/ui, OIDC, Helm — are all platform decisions; we follow them.

  • Vite + Module Federation for the build. Standalone and microfrontend builds from the same codebase via npm run build and npm run build-mf. The federation plugin (@originjs/vite-plugin-federation) is the platform standard for remote-loading.
  • @fcc/ui for components. Raiffeisen's internal design system, published to the bank's Artifactory. We never reinvent components — when the product needs something @fcc/ui doesn't have, we contribute upstream.
  • OIDC for identity. react-oidc-context against the bank's IdP. No bespoke auth.
  • jotai for state. Lightweight, composable, fits a single-product surface where Redux would be heavy.
  • single-spa-react + single-spa-css for the microfrontend integration boundary — the contract between this product and the shell.
  • Helm charts (production + proxy variants). Standard pattern; deployment is part of the codebase.

Solution

The product is a deposits-specific React app paired with a Kotlin BFF. The frontend builds as a self-contained app for local development and direct hosting, and as a Module Federation remote that the bank's shell mounts at runtime. The same TypeScript code paths serve both modes; the entrypoints differ, the product logic doesn't. The BFF (core-ui-bff) sits between the frontend and the bank's underlying account/deposit services and provides a stable, deposits-shaped API the UI can target without coupling to internal service boundaries. Helm charts cover application deployment and a proxy for the microfrontend hosting pattern.

Architecture

A single Vite/React/TypeScript codebase with two build configurations: vite.config.ts for the standalone build and vite.config.mf.ts for the Module Federation build. The MF build exposes the deposits surface as a remote via @originjs/vite-plugin-federation; the shell loads it through single-spa-react. Auth tokens flow from the shell to the remote through react-oidc-context. Components come from @fcc/ui.

core-ui-bff is a Kotlin 2.0 / Spring Boot 3.5 service on Java 21. It exposes the deposits HTTP API (account info, deposit catalog, lifecycle operations) as an OAuth2 resource server, calls downstream retail services (notably retail-account-api) via Spring Cloud OpenFeign, documents itself with Springdoc OpenAPI, and uses Arrow-kt for typed error handling. The same BFF serves both the standalone deposits UI and the deposits screens embedded in the operator workspace.

Key features shipped

  • Deposit product browsing and configuration
  • Deposit creation flow integrated with the bank's KYC/AML conventions
  • Deposit lifecycle screens (extension, early closure, partial withdrawal, terms management)
  • Microfrontend integration into the bank's retail-banking shell

Outcome

The deposits product runs in production as part of Raiffeisenbank Russia's retail-banking experience. The single-engineer engagement has held — throughput against the product roadmap matches the team's expectations for a permanent hire.

  • Live in production as a microfrontend
  • Continuous delivery into the bank's shell
  • One embedded topsweteam engineer carrying the workstream

Tech stack

Frontend build: Vite, Module Federation (@originjs/vite-plugin-federation), TypeScript Frontend app: React 18, jotai, react-router-dom, styled-components, date-fns Design system: @fcc/ui v12.x, @fcc/icons Auth: oidc-client-ts, react-oidc-context Microfrontend integration: single-spa-react, single-spa-css BFF (core-ui-bff): Kotlin 2.0, Spring Boot 3.5, Java 21, Spring OAuth2 Resource Server, Spring Cloud OpenFeign, Springdoc OpenAPI, Arrow-kt, Micrometer + Prometheus Deployment: Helm (application and proxy charts), Kubernetes

What we learned

  • Module Federation works when both sides treat it as a discipline. The shell and the remote each have to honor the contract; the embedded team makes that easy because there's only one team.
  • Inside an established platform, the cheapest engineer is the one who ships the most product, not the one who knows the most patterns. Every architectural decision is already made; the leverage is in product velocity.
  • Contributing upstream to the design system beats forking it locally. If the deposits product needs a component @fcc/ui lacks, the right move is to add it to @fcc/ui — not to one-off it inside this product.

tech

build
Vite, Module Federation, Gradle (Kotlin DSL)
frontend
React 18, TypeScript, Redux Toolkit, Redux Saga, jotai, react-hook-form + Zod, formik + yup, styled-components, @fcc/ui (Raiffeisen design system)
backend
Kotlin, Java 21, Spring Boot 3.x, Spring Data JPA, Spring Cloud OpenFeign, Spring Web Services, Spring Boot Artemis (JMS), IBM MQ (Jakarta), Resilience4j
data
PostgreSQL, DB2, Liquibase, Flyway, Redis, Apache POI, PDFBox, ICU4J
auth
OIDC via react-oidc-context, OAuth2 Resource Server, OTP signing
microfrontend
single-spa-react, single-spa-css
contract
OpenAPI 3 codegen on both sides, wsdl2java for SOAP integrations, Springwolf for JMS
ops
Springdoc, Micrometer + Prometheus, OTel tracing, Sonar, Allure, JaCoCo, ShedLock
deployment
Helm, Kubernetes, Raiffeisen Artifactory, GitLab CI
type any key to open chatopen chat