{"id":19422229,"url":"https://github.com/u-ways/spring-boot-reactive-microservice-kt","last_synced_at":"2026-04-13T13:04:38.197Z","repository":{"id":232885379,"uuid":"785390506","full_name":"u-ways/spring-boot-reactive-microservice-kt","owner":"u-ways","description":"A POC project to compare the development experience of building a reactive API using latest Spring Boot as opposed to Vert.x.","archived":false,"fork":false,"pushed_at":"2025-07-26T10:21:57.000Z","size":322,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-26T16:34:56.923Z","etag":null,"topics":["acceptance-test-driven-development","docker","domain-driven-design","gradle","hacktoberfest","kotlin","postgresql","rabbitmq","reactive","reactive-programming","spring-boot","testcontainers","webflux"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/u-ways.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2024-04-11T19:48:08.000Z","updated_at":"2025-07-26T10:22:01.000Z","dependencies_parsed_at":"2024-04-15T12:45:22.435Z","dependency_job_id":null,"html_url":"https://github.com/u-ways/spring-boot-reactive-microservice-kt","commit_stats":null,"previous_names":["u-ways/modern-reactive-spring-backend-kotlin","u-ways/spring-boot-reactive-microservice-kt"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/u-ways/spring-boot-reactive-microservice-kt","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/u-ways%2Fspring-boot-reactive-microservice-kt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/u-ways%2Fspring-boot-reactive-microservice-kt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/u-ways%2Fspring-boot-reactive-microservice-kt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/u-ways%2Fspring-boot-reactive-microservice-kt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/u-ways","download_url":"https://codeload.github.com/u-ways/spring-boot-reactive-microservice-kt/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/u-ways%2Fspring-boot-reactive-microservice-kt/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31753555,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-13T09:16:15.125Z","status":"ssl_error","status_checked_at":"2026-04-13T09:16:05.023Z","response_time":93,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["acceptance-test-driven-development","docker","domain-driven-design","gradle","hacktoberfest","kotlin","postgresql","rabbitmq","reactive","reactive-programming","spring-boot","testcontainers","webflux"],"created_at":"2024-11-10T13:32:44.194Z","updated_at":"2026-04-13T13:04:38.182Z","avatar_url":"https://github.com/u-ways.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Spring Boot Reactive Microservice (Kt)\n\n[![CICD](https://github.com/u-ways/spring-boot-reactive-microservice-kt/actions/workflows/CICD.yml/badge.svg)](https://github.com/u-ways/spring-boot-reactive-microservice-kt/actions/workflows/CICD.yml)\n[![Code Climate](https://badgen.net/badge/CodeClimate/A/green)](https://codeclimate.com/github/u-ways/spring-boot-reactive-microservice-kt)\n[![GitHub License](https://badgen.net/badge/license/BSD-3-Clause/blue)](https://github.com/u-ways/spring-boot-reactive-microservice-kt/blob/master/LICENSE)\n[![Awesome](https://awesome.re/badge.svg)](https://awesome.re)\n\n- [Background](#background)\n- [Katanox API](#katanox-api)\n- [Vert.x vs Spring WebFlux](#vertx-vs-spring-webflux)\n    * [The Streams Specification Vs The Reactive Manifesto](#the-streams-specification-vs-the-reactive-manifesto)\n    * [Personal Verdict](#personal-verdict)\n- [Implementation Details](#implementation-details)\n    * [Solution Architecture](#solution-architecture)\n    * [Other Practices and Technical Decisions](#other-practices-and-technical-decisions)\n    * [Algorithmic Solution](#algorithmic-solution)\n- [Usage](#usage)\n    * [Prerequisites](#prerequisites)\n    * [Running the Application](#running-the-application)\n    * [Contributing](#contributing)\n\n## Background\n\nOur older monolithic applications were built using an older generation of Spring Boot with vertical scaling architecture. \nWith the rise of cloud computing and the need for more scalable and resilient applications, we've moved towards a more \nmodern, reactive architecture. Our framework of choice was [Vert.x](https://vertx.io/), which allowed us to build reactive microservices \nthat could scale horizontally with ease.\n\nVert.x reactive model was a great experience and a great fit for our use case, it became our de-facto standard for building\nnew services. However, this made us neglect the Spring Boot ecosystem, which has been evolving rapidly and is becoming\na strong contender in the reactive space.\n\nThis project is a software's engineer take at building a modern reactive API using Spring Boot and Kotlin. The goal is \nto leverage as much as possible from the Spring Boot ecosystem and compare it to our current experience with Vert.x.\n\n## Katanox API\n\nI have chosen [Katanox API](https://docs.katanox.com/reference) as the base for this project mainly because their API\nis well-documented and provides a good use case for building a reactive API.\n\n\u003e Katanox is a direct booking API that allows Buyers and Suppliers to establish a partnership effortlessly in a B2B \n\u003e marketplace. We aim to open hotel sales to the next generation of travel sellers ranging from airlines to travel \n\u003e publishers, voice assistants to messaging apps.\n\u003e \n\u003e - Katanox is not a Channel Manager - it connects with different PMSs without the need to map rooms for new partners.\n\u003e - Katanox is not a GDS - direct deals are easily managed through a new technology that keeps your content updated.\n\u003e - Katanox is not an OTA - it is not even a channel. It is a platform where you have control over your partnerships.\n\u003e \n\u003e We want to drive innovation for Buyers and Suppliers and ultimately help the growth of the travel industry.\n\n- Source: [Katanox - What is Katanox?](https://support.katanox.com/en/articles/5485057-what-is-katanox)\n\nCheck them out, they have a great API and a great team behind it.\n\n## Vert.x vs Spring WebFlux\n\nYou might be interested in a technical comparison between Vert.x and Project Reactor.\nHere are some relevant (albeit some are old) resources that can help you with your research:\n\n- [**Reactive Architectures**](https://blog.rcode3.com/blog/vertx-vs-webflux/): Comparing Vert.x to Spring WebFlux.\n- [**Reactive Microservices with Spring**](https://www.youtube.com/watch?v=1F10gr2pbvQ): Conference talk on building reactive microservices with Spring.\n- [**Reactive Microservices with Vert.x**](https://www.youtube.com/watch?v=7IbdWcdlYOI): Conference talk on building reactive microservices with Vert.x.\n- [**SpringBoot Webflux vs Vert.x**](https://blog.rcode3.com/blog/vertx-vs-webflux/): Performance comparison for hello world case.\n- [**vertx-vs-spring-reactor**](https://github.com/ankushs92/vertx-vs-spring-reactor?tab=readme-ov-file): A benchmark comparing using Vertx vs Spring Reactor.\n\n### The Streams Specification Vs The Reactive Manifesto\n\nBoth Vert.x and [Project Reactor](https://projectreactor.io/) (What Spring WebFlux is based on) are based on the [Reactive Streams Specification](https://github.com/reactive-streams/reactive-streams-jvm?tab=readme-ov-file#reactive-streams),\nwhich in turn came about as a result of the [Reactive Manifesto](https://www.reactivemanifesto.org/). However, it's important\nto distinguish between the after mentioned specification and manifesto, for that, have a look at the AWS Whitepaper on\n[Reactive programming and reactive streams](https://docs.aws.amazon.com/whitepapers/latest/reactive-systems-on-aws/characteristics-of-reactive-systems.html).\n\n### Personal Verdict\n\nAlthough the SpringBoot ecosystem is extremely rich and well-supported, I found reactive Spring implementation locks you\ninto a specific set of types (e.g. returning an instance of `Mono\u003cT\u003e` or `Flux\u003cT\u003e` so it can be subscribed to at the end). \nAs a result, you are unable to leverage the full power of the Spring ecosystem. However, I found Project Reactor a joy to \nwork with as it's functional programming model and the reactive streams API are well-thought-out.\n\nIn contrast, Vert.x is much more minimalistic than Spring, and it's [architecture model](https://vertx.io/docs/vertx-core/java/#event_bus), with careful engineering,\ncan be abstracted away from the developer. This allows the developer to focus on the business logic and not on the framework,\nresulting in a more straightforward and cleaner codebase. However, the ecosystem is not as rich as Spring, and you might\nfind yourself building custom libraries to handle the complexity of your services.\n\nFor example, one of my favourite features of Vert.x is the [Verticle](https://vertx.io/docs/vertx-core/java/#_verticles) model, which allows you to build your services\nin a more modular way. Allowing your team members to work in multiple parts of the application without causing conflicts.\n\nAlthough, it's worth mentioning we have gone through a lot of Vert.x iterations to get the complexity right to reduce our \nTTM (Time to Market) via our own in-house Vert.x framework that is used for building new services. This involved trial \nand error, and we had to build a lot of custom solutions to handle the complexity of our services. So I am sure we can \nachieve the same with reactive Spring Boot with a bit more effort.\n\n## Implementation Details\n\n### Solution Architecture\n\n![Solution Architecture](./docs/Booking-System-Solution-Architecture.png)\n\nFor this project, I decided to go for a READ-ONLY microservice that will provide the availability of properties and the\nability to book a room. The \"pre-booking\" service will simulate an asynchronous flow via a `RabbitMQ` message broker, and\nthe \"reservation service\" will confirm and save the booking details to the database.\n\nOf course, this is a simplified version of the architecture, in a real-world scenario, we would have more services and\ncomplex provisioning logic involved in the booking process. However, for the sake of this project, I decided to keep it \nsimple.\n\nIt's also worth mentioning the \"Availability \u0026 Pre-Booking Service\" shouldn't be communicating with the Database directly,\nas it would complicate data synchronisation with the \"Reservation Service\". Instead, it would be better to have a repository\nservice that would handle the database operations. This would allow us to have a more decoupled architecture and a more\nscalable solution via an intermediary API layer which would mediate database operations. However, I wanted to use the \nR2DBC in this POC, and so I've overlooked this architectural decision.\n\n### Other Practices and Technical Decisions\n\nI have decided to follow DDD (Domain-Driven Design) principles for this project, and drive the implementation via ATDD\n(Acceptance Test-Driven Development). So the acceptance tests are the driving force behind the implementation features.\n\nOn top of that, jOOQ will be used to generate the database schema and the queries, and Flyway will be used to manage the\ndatabase migrations. This will allow us to have a [database-first approach](https://www.jooq.org/#a=usp-database-first) \nto the implementation and a typesafe database object referencing.\n\nMetrics scraping will be done via Micrometer and Prometheus, and the logs (in-production) will be sent as JSON to a\ncentralised logging system (e.g. [ELK stack](https://aws.amazon.com/what-is/elk-stack/)). Readiness and Liveness probes \nwill be implemented via Spring Boot Actuator to allow Kubernetes to manage the lifecycle of the application.\n\nI will also admit I did not have the time to do a 100% test coverage so many of the sad-path scenarios are not covered,\nlikewise the happy-path scenarios are not fully covered. However, I have tried to cover the most important scenarios.\n\n### Algorithmic Solution\n\nBulk of the work was done in the availability service, where we calculate the availability of a given hotel ID rooms\nbased on the check-in and check-out dates. The algorithm is quite simple, we have to check if the room is available for\nthe given dates, and if it is, we have to calculate the price based on set of associated prices (Details can be found\nin the [AvailabilityService](./src/main/kotlin/com/katanox/api/domain/availability/AvailabilityService.kt) kdoc).\n\n![Availability Service Sequence Diagram](./docs/availability-service-sequence-diagram.png)\n\nThe implementation is driven via the [AvailabilityEndpointIT](./src/test/kotlin/com/katanox/api/acceptance/AvailabilityEndpointIT.kt) acceptance tests.\n\nLikewise, the booking service implementation is driven via the [BookingEndpointIT](./src/test/kotlin/com/katanox/api/acceptance/BookingEndpointIT.kt) acceptance tests. In which it \nrelies on the availability service to check if the requested room is \"really\" available for the given dates. Therefore,\nwe enabled a caching layer to reduce the number of calls to the availability repository. You can see the implementation \ndetails in the [BookingService](./src/main/kotlin/com/katanox/api/domain/booking/BookingService.kt) class.\n\nThis is by no means a perfect solution, and there are many ways to improve it, but the reactive programming patterns \nvia Project-Reactor are well-illustrated in the implementation.\n\n## Usage\n\n### Prerequisites\n\n- You should have [Gradle](https://gradle.org/install/) installed to build the application.\n- You also need [Docker](https://docs.docker.com/get-docker/) installed to deploy the application and accompanying infrastructure.\n\n### Running the Application\n\nWe use [Makefile](./Makefile) to simplify the build and run process.\n\nSimply run:\n\n```bash\nmake deploy-app\n```\n\nand everything will be set and ran for you. You can also use `make undeploy-app` to gracefully stop the \napplication and tear down the containers. For checking the health status of the application you can run:\n\n```bash\ncurl -sv http://localhost:8080/actuator/health | jq\n```\n\nActuator discovery is turned on, so accessing [http://localhost:8080/actuator](http://localhost:8080/actuator) will \ngive you a list of available actuator endpoints to probe. (e.g. flyway, metrics, health, etc.)\n\n**TIP**: check out the [./local](./local) directory for handy SQL inserts and open HTTP requests files.\n\n### Contributing\n\nAlthough this is more of an educational/research project, I am open to contributions. If you have any suggestions or\nimprovements, feel free to open a PR or an issue.\n\nI am a big fan of providing a great Developer Experience (DX), so I've allocated time in making the build \nprocess as seamless as possible. When you try generating jOOQ classes, you will trigger the appropriate Gradle\ntask to generate the classes without manual intervention. Task input/output caching is also configured.\n\nIntegration tests are ran via testcontainers, and they're gracefully stopped after the tests are done via Ryuk.\n\nAlso, a JVM toolchain is provided to ensure the correct version (21) of Java is being used.\n\nI advise checking out the [build.gradle.kts](./build.gradle.kts) and the [Makefile](./Makefile) to understand the\nbuild process and what's available to you.\n\n___\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fu-ways%2Fspring-boot-reactive-microservice-kt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fu-ways%2Fspring-boot-reactive-microservice-kt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fu-ways%2Fspring-boot-reactive-microservice-kt/lists"}