<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Joao Marcos Costa Salles</title>
    <description>The latest articles on DEV Community by Joao Marcos Costa Salles (@joaosalles).</description>
    <link>https://dev.to/joaosalles</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F410269%2Ffe574362-db0a-491b-9071-9ae02177717a.png</url>
      <title>DEV Community: Joao Marcos Costa Salles</title>
      <link>https://dev.to/joaosalles</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/joaosalles"/>
    <language>en</language>
    <item>
      <title>Creating a modular Kotlin project using gradle.</title>
      <dc:creator>Joao Marcos Costa Salles</dc:creator>
      <pubDate>Wed, 27 May 2026 22:58:04 +0000</pubDate>
      <link>https://dev.to/joaosalles/creating-a-modular-kotlin-project-using-gradle-23g3</link>
      <guid>https://dev.to/joaosalles/creating-a-modular-kotlin-project-using-gradle-23g3</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;The idea of building a system entirely composed of microservices is always tempting for a developer, whether for the challenge itself or to stay ahead of scaling needs. However, analyzing trade-offs and choosing what best fits our context is also part of our profession.&lt;br&gt;
A very common decision today at the beginning of a project is to build modular projects as a way of anticipating a future need to split out a dedicated service. This approach adds less initial complexity than a microservices architecture, while keeping modules sufficiently independent for a potential future separation if needed.&lt;/p&gt;

&lt;p&gt;In this article, I will show hot to set up Gradle to enable modules on a monolithic project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-inflation/src/main/kotlin/com/salles/scrapping
├── data        # DTO declarations
├── db
│   ├── tables  # Persistence table declarations
├── domain      # Business logic declarations
├── repositories
├── routes
├── services
└── scrapper    # Feature that could move to another project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To a modular monolith:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-inflation
├── gradle
│   └── libs.versions.toml
├── myInflation  # Module to list prices and products
│   ├── src
│   └── build.gradle.kts
├── root         # Module to link other modules and set up Ktor
│   ├── src
│   └── build.gradle.kts
├── scrapper     # Module for scraping, which may move in the future
│   ├── src
│   └── build.gradle.kts
├── domain       # Module for domain declarations
│   ├── src
│   └── build.gradle.kts
├── data         # Module for the persistence layer
│   ├── src
│   └── build.gradle.kts
├── build.gradle.kts
└── settings.gradle.kts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Module Declaration
&lt;/h2&gt;

&lt;p&gt;It is necessary to declare the modules in settings.gradle.kts. In my case:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;include(":myInflation", ":root", ":scrapper", ":data", ":domain")&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you use the same name as the folder, Gradle will find it automatically. If for some reason you need a different name, you can map it explicitly:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;project(":myInflation").projectDir = file("core")&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Shared Version Catalog
&lt;/h2&gt;

&lt;p&gt;It is very important to create a libs.versions.toml file in the folder structure shown above. In it, we will maintain the versions of all libraries, ensuring consistency across all modules while gaining the benefits of caching and reducing build size. The file will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[versions]
kotlin = "2.3.20"
kotlinx-serialization = "1.9.0"

[libraries]
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization" }

[plugins]
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Module Dependency Configuration
&lt;/h2&gt;

&lt;p&gt;Configuring dependencies between modules is straightforward. I will configure only the root module here, but other modules may also depend on the domain module, for example, and will need their own declarations.&lt;br&gt;
Inside &lt;em&gt;root/build.gradle.kts&lt;/em&gt;, add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dependencies {
    implementation(project(":domain"))
    implementation(project(":data"))
    implementation(project(":myInflation"))
    implementation(project(":scrapper"))
    // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only the root module contains the server runner, so add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;application {
    mainClass = "io.ktor.server.netty.EngineMain"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we need to define which function should run to start the server. In &lt;em&gt;root/src/main/resources/application.yaml&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ktor:
  application:
    modules:
      - com.salles.root.ApplicationKt.module
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Removing Unnecessary Dependencies
&lt;/h2&gt;

&lt;p&gt;Finally, we can trim each module's dependencies. To do so, we will use the &lt;a href="https://github.com/autonomousapps/dependency-analysis-gradle-plugin" rel="noopener noreferrer"&gt;dependency-analysis-gradle-plugin&lt;/a&gt; to analyze module dependencies.&lt;/p&gt;

&lt;p&gt;In &lt;em&gt;libs.versions.toml&lt;/em&gt;, add the plugin version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[versions]
# ...
dependency-analysis = "3.13.0"

[plugins]
# ...
dependency-analysis = { id = "com.autonomousapps.dependency-analysis", version.ref = "dependency-analysis" }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In build.gradle.kts, add:&lt;br&gt;
subprojects {&lt;br&gt;
    apply(plugin = "com.autonomousapps.dependency-analysis")&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;To run the analysis:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./gradlew &amp;lt;module&amp;gt;:projectHealth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check &lt;em&gt;{module}/build/reports/dependency-analysis&lt;/em&gt; for the report and change it if it makes sense.&lt;/p&gt;

&lt;p&gt;With this, the project is configured for a modular structure. However, simply moving files is not enough — inter-module dependencies will still exist. It is necessary to define business logic that is exclusive to each feature module, but that is outside the scope of this article.&lt;/p&gt;

&lt;p&gt;The dependency graph ends up looking like this. Note that scrapper and myInflation are now separated, with not direct dependency between the,:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv1h20t9e34hqianydoj2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv1h20t9e34hqianydoj2.png" alt="Dependency Diagram" width="597" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;References:&lt;/p&gt;

&lt;p&gt;my-inflation: &lt;a href="https://github.com/JoaoSalles/my-inflation-api" rel="noopener noreferrer"&gt;https://github.com/JoaoSalles/my-inflation-api&lt;/a&gt;&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>gradle</category>
    </item>
  </channel>
</rss>
