<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	 xmlns:media="http://search.yahoo.com/mrss/" >

<channel>
	<title>Kotlin : A concise multiplatform language developed by JetBrains | The JetBrains Blog</title>
	<atom:link href="https://blog.jetbrains.com/kotlin/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.jetbrains.com</link>
	<description>Developer Tools for Professionals and Teams</description>
	<lastBuildDate>Wed, 13 May 2026 08:54:15 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://blog.jetbrains.com/wp-content/uploads/2024/01/cropped-mstile-310x310-1-32x32.png</url>
	<title>Kotlin : A concise multiplatform language developed by JetBrains | The JetBrains Blog</title>
	<link>https://blog.jetbrains.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>The Road to Name-Based Destructuring</title>
		<link>https://blog.jetbrains.com/kotlin/2026/05/the-road-to-name-based-destructuring/</link>
		
		<dc:creator><![CDATA[Viliam Sedliak]]></dc:creator>
		<pubDate>Wed, 13 May 2026 08:52:35 +0000</pubDate>
		<featuredImage>https://blog.jetbrains.com/wp-content/uploads/2026/05/KT-social-BlogFeatured-1280x720-1-4.png</featuredImage>		<category><![CDATA[news]]></category>
		<category><![CDATA[tutorials]]></category>
		<category><![CDATA[compiler]]></category>
		<category><![CDATA[kotlin]]></category>
		<category><![CDATA[tutorial]]></category>
		<guid isPermaLink="false">https://blog.jetbrains.com/?post_type=kotlin&#038;p=706759</guid>

					<description><![CDATA[TL;DR New “val inside parentheses” syntax is being introduced to allow for name-based destructuring. Additionally, new syntax with square brackets is being introduced for positional destructuring. Both are currently Experimental (enabled using the -Xname-based-destructuring=only-syntax compiler argument) and will become Stable in a future release. In the distant future, the behavior of the “val outside parentheses” [&#8230;]]]></description>
										<content:encoded><![CDATA[
<div style="background: #f7f3ff;padding: 20px 24px;margin: 24px 0;border-radius: 8px">
  <h2 style="margin-top: 0">TL;DR</h2>
  <ul style="margin-bottom: 0">
    <li>
      New “val inside parentheses” syntax is being introduced to allow for name-based destructuring. Additionally, new syntax with square brackets is being introduced for positional destructuring.
      <ul>
        <li>
          Both are currently Experimental (enabled using the <code>-Xname-based-destructuring=only-syntax</code> compiler argument) and will become Stable in a future release.
        </li>
      </ul>
    </li>
    <li>
      In the distant future, the behavior of the “val outside parentheses” syntax for destructuring will change from being position-based to name-based.
      <ul>
        <li>
          There will be a long migration period before the default changes, and tooling is already in place to help with migration.
        </li>
        <li>
          You can already make the switch to the new behavior (<code>-Xname-based-destructuring=complete</code>), but note its Experimental status.
        </li>
      </ul>
    </li>
    <li>
      The compiler ships with migration helpers that will be enabled by default for a few versions, and it will be some time before the new behavior becomes the default.
      <ul>
        <li>
          You can enable these helpers now by using <code>-Xname-based-destructuring=name-mismatch</code>.
        </li>
      </ul>
    </li>
  </ul>
</div>



<p>Kotlin is changing, with names set to become central in destructuring. In the future, <code>val (name, age) = person</code> will extract the <code>name</code> and <code>age</code> properties from the <code>person</code> value, regardless of the way and order in which they were defined. This marks a change from the current approach to destructuring, in which the position is the key element. This blog post explains the reasoning behind this change, the migration strategy, and how Kotlin&#8217;s tooling supports it.</p>



<h2 class="wp-block-heading">Why destructure by name instead of position?</h2>



<p><a href="https://kotlinlang.org/docs/destructuring-declarations.html" target="_blank" rel="noreferrer noopener">Destructuring</a> is most commonly used to access properties from data classes. For example, we can define a <code>Person</code> class as follows:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">data class Person(val name: String, val age: Int)</pre>



<p>Then we can extract several of the primary properties in a single go. This is what we call <strong>destructuring</strong> the value into its components.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fun isValidPerson(p: Person) {
  val (name, age) = p
  return name.isNotEmpty() &amp;&amp; age >= 0
}</pre>



<p>Currently, destructuring is done by position. The variables we introduce in a destructuring declaration often follow the names of the properties in the data class, but there&#8217;s no such requirement in the language.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">// this is exactly the same function as above
fun isValidPerson(p: Person) {
  val (foo, bar) = p
  return foo.isNotEmpty() &amp;&amp; bar >= 0
}</pre>



<p>This <strong>lack of connection</strong> can cause problems, as it is very easy to inadvertently swap the order of two properties. This mistake may be caught later because of non-matching types, but it appears far from the actual origin.<br><br>The way in which components relate to primary properties also <strong>hinders refactoring</strong>. For example, we cannot move the <code>age</code> property to be computed and still retain the nice data class syntax. Imagine we make the following change:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">data class Person(val name: String, val birthdate: Date) {
  val age = (Date.now() - birthdate).years
}</pre>



<p>Now every destructuring declaration suddenly changes from <code>age</code> to <code>birthdate</code>! To be clear, source compatibility is still possible, but you need to do a lot more work.</p>



<p>The current approach to destructuring is also at <strong>odds with abstraction</strong>. If we turned Person into an interface, previous instances of destructuring would no longer be valid. We could work around this by introducing our own component functions, but this is usually seen as advanced. As a result, most interfaces do not provide such facilities.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">interface Person {
  val name: String
  val age: Int

  operator fun component1(): String = name
  operator fun component2(): Int    = age
}</pre>



<p>These problems go away if destructuring depends on <strong>names instead of positions</strong>. It doesn&#8217;t matter if you rearrange the order, change a computed property into a primary one or vice versa, or define a property in a class, interface, or object. The property’s name is a stable characteristic, which means that the source does not require any changes.</p>



<h2 class="wp-block-heading">The new syntax</h2>



<p><em>You can enable the new syntax by passing <code>-Xname-based-destructuring=only-syntax</code> as a </em><a href="https://kotlinlang.org/docs/whatsnew2320.html#name-based-destructuring" target="_blank" rel="noreferrer noopener"><em>compiler argument</em></a><em>.</em></p>



<p>Without further ado, let&#8217;s look at the <strong>new syntax</strong>, which uses names for destructuring. Instead of a single val outside of the parentheses, you use val for each property <strong>inside</strong> the parentheses.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fun isValidPerson(p: Person): Boolean {
  (val name, val age) = p
  return name.isNotEmpty() &amp;&amp; age >= 0
}</pre>



<p>As expected, the order in which we write <code>val name</code> and <code>val age</code> in the example above doesn’t matter. This new syntax also supports <strong>renaming</strong> for cases in which the new variable you want to define is not the same as the property you want to access.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fun isValidPerson(p: Person): Boolean {
  (val age, val theName = name) = p
  return theName.isNotEmpty() &amp;&amp; age >= 0
}</pre>



<p>Destructuring based on position is still important for a few use cases. Pairs and triples, for example, don&#8217;t have names for their components at a conceptual level, and there&#8217;s no intention to require littering code that uses them with <code>first</code> and <code>second</code>. Position-based destructuring can also be used for collections, and in that case, there are no available properties. The new syntax for position-based destructuring uses square brackets – mirroring the syntax of upcoming collection literals. You can choose whether to put <code>val</code> inside or outside the brackets.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fun isZero(point: Pair&lt;Int, Int>): Boolean {
  val [x, y] = point      // one way
  [val x, val y] = point  // or another
  return x == 0 &amp;&amp; y == 0
}</pre>



<p>All of this new syntax is available anywhere you can destructure, including lambda expressions and loops.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">// suggested new syntax for iterating through a map
for ([key, value] in map) {
  // work with each entry
}

person?.let { (val name, val years = age) -> "$name is $years years old" }</pre>



<p>To reiterate: This is all <strong>new</strong> syntax. As of version 2.3.20, the compiler knows what it means, and we intend to keep this syntax once the feature reaches Stable status.</p>



<h2 class="wp-block-heading">Repurposing parentheses</h2>



<p><em>At some point in the future, we intend for all destructuring using parentheses to be name-based. You can actually experience this future now by using the <code>-Xname-based-destructuring=complete</code> compiler argument.</em></p>



<p>If you already have a project, though, making the switch could have a major impact. The most visible issue would be if destructuring stops working, and the code needs to be updated. A more dangerous one would be destructuring declarations that remain valid but change the meaning.<br><br>For that reason, the compiler ships a migration helper under the <code>-Xname-based-destructuring=name-mismatch</code> compiler argument. When enabled, the compiler gives a warning in cases where the behavior is inconsistent between position-based and name-based destructuring or where the code won&#8217;t be accepted once destructuring with parentheses is no longer positional.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">// accepted by both with the same behavior 
val (name, age) = person

// warning: accepted by both, but the behavior changes
val (age, name) = person

// warning: accepted only by position-based destructuring
val (personName, personAge) = person
// the IDE suggests potential fixes
// - renaming: (val personName = name, val personAge = age) = person
// - square brackets: val [personName, personAge] = person</pre>



<h2 class="wp-block-heading">The future</h2>



<p>As hinted in this post, there will be ample time to migrate to the new name-based destructuring. Our current timeline looks as follows:</p>



<ul>
<li>As of version 2.3.20, name-based destructuring is Experimental, meaning that you need a special compiler argument to use it.
<ul>
<li>Support in IntelliJ IDEA may be lacking, especially for migration.<br></li>
</ul>
</li>



<li>With version 2.5.0 (at the end of 2026), the feature will become Stable.
<ul>
<li>The new syntax will be available without additional configuration.</li>



<li>The compiler will start reporting migration hints, and IntelliJ IDEA will include inspections and quick-fixes to help with the process.</li>



<li>This stage roughly corresponds to <code>name-mismatch</code> in compiler arguments, although we may make some adjustments to reporting depending on user feedback.<br></li>
</ul>
</li>



<li>By version 2.7.0 (at the end of 2027), destructuring with parentheses will be name-based.
<ul>
<li>You can migrate to this stage earlier by using <code>complete</code> in compiler arguments.<br></li>
</ul>
</li>
</ul>



<p>This is a big change, and we don&#8217;t want to rush it. If at any point during 2027 it becomes clear that the ecosystem is not ready, we may postpone the change until another major version.</p>



<p>At <strong>no</strong> <strong>point are we</strong> <strong>deprecating</strong> the generation of component functions for <strong>data classes</strong>. Data classes will still generate the same bytecode – name-based destructuring is a feature for use sites. However, we plan to introduce multi-field value classes without component functions. That means that destructuring for value classes will only be name-based.</p>



<h2 class="wp-block-heading">References</h2>



<ul>
<li><a href="https://kotlinlang.org/docs/whatsnew2320.html#name-based-destructuring" target="_blank" rel="noreferrer noopener">Release notes for Kotlin 2.3.20</a>, the first version to offer name-based destructuring.</li>



<li><a href="https://github.com/Kotlin/KEEP/blob/main/proposals/KEEP-0438-name-based-destructuring.md" target="_blank" rel="noreferrer noopener">Design document</a> (KEEP) for the feature and corresponding <a href="https://github.com/Kotlin/KEEP/discussions/438" target="_blank" rel="noreferrer noopener">public discussion</a>.</li>
</ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Kotlin Ecosystem Mentorship Program: Results and Winners</title>
		<link>https://blog.jetbrains.com/kotlin/2026/05/kotlin-ecosystem-mentorship-program/</link>
		
		<dc:creator><![CDATA[Ksenia Shneyveys]]></dc:creator>
		<pubDate>Thu, 07 May 2026 14:45:45 +0000</pubDate>
		<featuredImage>https://blog.jetbrains.com/wp-content/uploads/2026/05/KT-social-BlogFeatured-1280x720-1-2.png</featuredImage>		<category><![CDATA[education]]></category>
		<category><![CDATA[news]]></category>
		<category><![CDATA[kotlin-foundation]]></category>
		<category><![CDATA[open-source]]></category>
		<guid isPermaLink="false">https://blog.jetbrains.com/?post_type=kotlin&#038;p=705949</guid>

					<description><![CDATA[In the Kotlin Ecosystem Mentorship Program pilot, mentors and mentees worked together on real Kotlin open-source projects to make their first meaningful community contribution. Four pairs successfully completed the two-month program, and one eligible pair was randomly selected in the prize drawing to receive the grand prize – a trip to KotlinConf 2026 in Munich! [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>In the <a href="https://blog.jetbrains.com/kotlin/2026/02/kotlin-ecosystem-mentorship/" target="_blank" rel="noreferrer noopener">Kotlin Ecosystem Mentorship Program</a> pilot, mentors and mentees worked together on real Kotlin open-source projects to make their first meaningful community contribution. Four pairs successfully completed the two-month program, and one eligible pair was randomly selected in the prize drawing to receive the grand prize – a trip to KotlinConf 2026 in Munich!</p>



<p>Congratulations to the winners:</p>



<ul>
<li>Mentor: Ruslan (<a href="https://github.com/yet300" target="_blank" rel="noreferrer noopener">yet300</a>)</li>



<li>Mentee: Clare Kinery (<a href="https://github.com/kinerycl" target="_blank" rel="noreferrer noopener">kinerycl</a>)</li>



<li>Project: <a href="https://github.com/permissionlesstech/bitchat-android" target="_blank" rel="noreferrer noopener">bitchat-android</a></li>
</ul>



<div class="buttons">
        <div class="buttons__row">
            <a class="ek-link jb-download-button" title="Join the KEMP Slack channel" href="https://slack-chats.kotlinlang.org/c/kotlin-ecosystem-mentorship-program" target="_blank" rel="noopener" data-test="blog-article-cta" data-cl="true">Join the KEMP Slack channel</a>
         </div>
</div>



<p>Ruslan’s and Clare’s collaboration focused on the Android client of BitChat, where Clare contributed UI and UX improvements that brought the Android experience closer to platform conventions and enhanced overall polish and accessibility.</p>



<p>Clare submitted and merged two pull requests: <a href="https://github.com/permissionlesstech/bitchat-android/pull/680" target="_blank" rel="noreferrer noopener">PR #680</a> and <a href="https://github.com/permissionlesstech/bitchat-android/pull/682" target="_blank" rel="noreferrer noopener">PR #682</a>. Her work improved BitChat’s voice note styling, camera and audio controls, dark/light theme support, visual hierarchy, and press interaction feedback.</p>



<p>Ruslan shared that Clare adapted quickly to the codebase and was able to work independently after the initial alignment. Their collaboration started with a kickoff call and continued asynchronously through chat and GitHub.</p>



<p>“Clare demonstrated strong problem-solving skills, attention to detail, and a solid understanding of UI/UX principles”, said Ruslan.</p>



<p>For Clare, the biggest takeaway was not just the code itself, but understanding the realities of open-source collaboration.</p>



<p>“As a developer who had never contributed to open source before, the biggest thing I learned was how open-source collaboration actually works. This program made it feel approachable and far less intimidating than I ever expected. I genuinely don’t think I would have taken that leap without it”, she commented.</p>



<h1 class="wp-block-heading">Other participants</h1>



<p>We received 80 mentee applications and 29 mentor applications – a clear sign of strong community interest in this kind of initiative, so we plan to continue the program.</p>



<p>For this pilot, we selected ten pairs. Eight remained active through the middle of the program, and four completed it successfully. These successful pairs contributed across different parts of the Kotlin ecosystem and Kotlin-related projects, including the Android UI, developer tooling, documentation, CI/CD, and multiplatform libraries.</p>



<p>We also want to recognize the other pairs who successfully completed the program:</p>



<p>Mentor: <a href="https://github.com/MohamedRejeb" target="_blank" rel="noreferrer noopener">Mohamed Rejeb</a></p>



<p>Mentee: <a href="https://github.com/deshkaustubh" target="_blank" rel="noreferrer noopener">Kaustubh Deshpande</a></p>



<p>Project: <a href="https://github.com/MohamedRejeb/Calf" target="_blank" rel="noreferrer noopener">Calf</a></p>



<p>Kaustubh contributed across several areas of the project, including dependency updates and CI/CD automation.</p>



<p>Mentor: <a href="https://github.com/Nek-12" target="_blank" rel="noreferrer noopener">Nikita Vaizin</a></p>



<p>Mentee: <a href="https://github.com/anshu7vyas" target="_blank" rel="noreferrer noopener">Anshul Vyas</a></p>



<p>Project: <a href="https://github.com/respawn-app/FlowMVI" target="_blank" rel="noreferrer noopener">FlowMVI</a></p>



<p>Anshul fixed a bug in the metrics module and contributed to the migration guide that helps developers move from MVVM to FlowMVI.</p>



<p>Mentor: <a href="https://github.com/tunjid" target="_blank" rel="noreferrer noopener">Adetunji Dahunsi</a></p>



<p>Mentee: <a href="https://github.com/HI-JIN2" target="_blank" rel="noreferrer noopener">Yu Jin</a></p>



<p>Project: <a href="https://github.com/tunjid/heron" target="_blank" rel="noreferrer noopener">heron</a></p>



<p>Yu Jin worked on improvements related to input handling and developer-facing issues, with a focus on making the project easier to use and maintain.</p>



<h1 class="wp-block-heading">What we learned</h1>



<p>Here are a few valuable takeaways from the participants’ feedback:</p>



<ul>
<li>Clear task scoping matters. Start with work that is concrete, manageable, and reviewable within the program timeline.</li>



<li>Asynchronous mentorship can work well, but only when expectations are explicit, and collaborators align early on communication style, task size, and review cycles.</li>



<li>The program creates value on both sides. Mentees gain confidence, workflow knowledge, and real experience. Mentors get fresh contributions, a chance to improve onboarding in their own projects, and a reminder that open source becomes healthier when maintainers make room for new contributors.</li>
</ul>



<p>Thank you to all mentors and mentees who joined the first Kotlin Ecosystem Mentorship cohort! We’re especially grateful to the maintainers who opened their projects to newcomers and invested time in guidance, reviews, and support.</p>



<p>Congratulations again to Ruslan and Clare, who were selected in the KotlinConf trip prize drawing, and to all four pairs who successfully completed the program.</p>



<p>To stay updated on future programs, <a href="https://slack-chats.kotlinlang.org/c/kotlin-ecosystem-mentorship-program" target="_blank" rel="noopener">join the KEMP Slack channel</a>. See you there!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Kodee’s Kotlin Roundup: Golden Kodee Finalists, Kotlin 2.4.0-Beta2, and New Learning Resources</title>
		<link>https://blog.jetbrains.com/kotlin/2026/05/kodees-kotlin-roundup-golden-kodee-finalists-kotlin-2-4-0-beta2-and-new-learning-resources/</link>
		
		<dc:creator><![CDATA[Viliam Sedliak]]></dc:creator>
		<pubDate>Mon, 04 May 2026 07:56:26 +0000</pubDate>
		<featuredImage>https://blog.jetbrains.com/wp-content/uploads/2026/04/KT-social-BlogFeatured-1280x720-1-3.png</featuredImage>		<category><![CDATA[news]]></category>
		<category><![CDATA[kotlin-roundup]]></category>
		<guid isPermaLink="false">https://blog.jetbrains.com/?post_type=kotlin&#038;p=702208</guid>

					<description><![CDATA[Hi everyone! April brought exciting community news with the announcement of the Golden Kodee finalists, along with Kotlin and tooling releases, multiplatform progress, and fresh backend resources. I also came across the new Kotlin Professional Certificate on LinkedIn Learning, which is a great way to build your skills. And if you want something more playful, [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Hi everyone! April brought exciting community news with the announcement of the Golden Kodee finalists, along with Kotlin and tooling releases, multiplatform progress, and fresh backend resources. I also came across the new Kotlin Professional Certificate on LinkedIn Learning, which is a great way to build your skills. And if you want something more playful, I found a fun way to practice coroutines. Here are the stories that stood out to me most.</p>


            <div class="newsletter">
                            <h2>Kodee-Approved Spotlight</h2>
                                                            <article class="newsletter__post">
                                                                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="newsletter__post-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/04/meta-kotlinconf-img.png" alt="KotlinConf 2026 is almost here">
                                                                            <div class="newsletter__post-text">
                                                            <h3>KotlinConf 2026 is almost here</h3>
                                                        <p>KotlinConf 2026 is just around the corner, and the excitement is definitely building. On May 20–22, more than 2,000 Kotlin developers from around the world will gather in Munich to share ideas, learn from each other, and connect. If you cannot make it in person, you can still join online – the conference will be livestreamed on the <a href="https://www.youtube.com/c/Kotlin" target="_blank" rel="noopener noreferrer">Kotlin YouTube channel</a>. I’ll be there in Munich, but I definitely recommend tuning in to catch the key announcements and talks as they happen.</p>
                                                            <a href="https://kotlinconf.com/schedule/?day=2026-05-21" class="btn" target="_blank" rel="noopener">Join KotlinConf</a>
                                                    </div>
                    </article>
                                    <article class="newsletter__post">
                                                                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="newsletter__post-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/04/awards-preview.png" alt="The Golden Kodee finalists have been officially named">
                                                                            <div class="newsletter__post-text">
                                                            <h3>Golden Kodee finalists</h3>
                                                        <p>The Golden Kodee finalists have been announced! The top three nominees in each category will be invited to KotlinConf in Munich, where one winner in each category will receive a Golden Kodee award. It is a great way to celebrate people who share knowledge, organize events, inspire others, and help grow the Kotlin community.</p>
                                                            <a href="https://kotlinconf.com/awards" class="btn" target="_blank" rel="noopener">Meet the finalists</a>
                                                    </div>
                    </article>
                                    <article class="newsletter__post">
                                                                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="newsletter__post-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/04/KT-social-BlogFeatured-1280x720-1-2.png" alt="Kotlin release updates">
                                                                            <div class="newsletter__post-text">
                                                            <h3>Kotlin release updates</h3>
                                                        <p>April brought two Kotlin release updates. Kotlin 2.4.0-Beta2 offers an early look at what’s coming next across the language, the standard library, the JVM, Kotlin/Native, and the compiler. <a href="https://github.com/JetBrains/kotlin/releases/tag/v2.3.21" target="_blank" rel="noopener">Kotlin 2.3.21</a> focuses on performance improvements and bug fixes for the 2.3 release.</p>
                                                            <a href="https://kotlinlang.org/docs/whatsnew-eap.html" class="btn" target="_blank" rel="noopener">See what’s new in Kotlin 2.4.0-Beta2</a>
                                                    </div>
                    </article>
                                    <article class="newsletter__post">
                                                                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="newsletter__post-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/04/IntelliJ-IDEA-2026.1.png" alt="IntelliJ IDEA 2026.1">
                                                                            <div class="newsletter__post-text">
                                                            <h3>IntelliJ IDEA 2026.1</h3>
                                                        <p>IntelliJ IDEA 2026.1 brings improvements that many Kotlin developers will notice in their daily work. From general performance enhancements to better language and framework support, this release is a strong ecosystem update and an important part of the Kotlin developer experience.</p>
                                                            <a href="https://www.jetbrains.com/idea/whatsnew/" class="btn" target="_blank" rel="noopener">Explore the release</a>
                                                    </div>
                    </article>
                                    <article class="newsletter__post">
                                                                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="newsletter__post-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/04/KM-social-BlogFeatured-1280x720-1.png" alt="Helping Decision-Makers Say Yes to Kotlin Multiplatform (KMP)">
                                                                            <div class="newsletter__post-text">
                                                            <h3>Helping Decision-Makers Say Yes to Kotlin Multiplatform (KMP)</h3>
                                                        <p>Adopting Kotlin Multiplatform is easier when the business value is clear. I found this guest post from Touchlab useful because it explains how KMP can improve delivery speed, reduce risk, and support long-term product strategy.</p>
                                                            <a href="https://blog.jetbrains.com/kotlin/2026/04/helping-decision-makers-say-yes-to-kmp/" class="btn" target="_blank">Read the post</a>
                                                    </div>
                    </article>
                                    <article class="newsletter__post">
                                                                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="newsletter__post-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/Blog-featured-1.png" alt="KotlinConf’26 Speakers: In Conversation With Lena Reinhard">
                                                                            <div class="newsletter__post-text">
                                                            <h3>KotlinConf’26 Speakers: In Conversation With Lena Reinhard</h3>
                                                        <p>Ahead of KotlinConf’26, I found this interview with Lena Reinhard interesting because it explores what it means to build a career in tech today, especially when old promises no longer feel certain. It covers leadership, uncertainty, the productivity debate in the age of AI, and the human side of our industry.</p>
                                                            <a href="https://blog.jetbrains.com/kotlin/2026/04/kotlinconf-26-speakers-in-conversation-with-lena-reinhard/" class="btn" target="_blank">Read the interview</a>
                                                    </div>
                    </article>
                                    <article class="newsletter__post">
                                                                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="newsletter__post-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/04/KT-social-BlogFeatured-1280x720-1-1.png" alt="Kotlin Professional Certificate by JetBrains – Now on LinkedIn Learning">
                                                                            <div class="newsletter__post-text">
                                                            <h3>Kotlin Professional Certificate by JetBrains on LinkedIn Learning</h3>
                                                        <p>Looking to build your Kotlin skills? The Kotlin Professional Certificate by JetBrains is now available on LinkedIn Learning. In less than 12 hours, you can go through four courses, pass the final exam, and earn a certificate you can share on your LinkedIn profile.</p>
                                                            <a href="https://kotl.in/kotlin-professional-certificate" class="btn" target="_blank" rel="noopener">Start learning</a>
                                                    </div>
                    </article>
                                    <article class="newsletter__post">
                                                                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="newsletter__post-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/04/KG-social-BlogFeatured-1280x720-1-3.png" alt="Koog updates for the JVM ecosystem">
                                                                            <div class="newsletter__post-text">
                                                            <h3>Koog updates for the JVM ecosystem</h3>
                                                        <p>Koog had a busy month, and I found these two updates useful for JVM developers. First, Koog now offers an idiomatic Java API, making it easier for Java teams to build agent workflows. Second, <a href="https://blog.jetbrains.com/ai/2026/04/introducing-koog-integration-for-spring-ai-smarter-orchestration-for-your-agents/" target="_blank">Koog integrates with Spring AI</a>, helping Kotlin and Spring-based projects use Koog in a familiar setup.</p>
                                                            <a href="https://blog.jetbrains.com/ai/2026/03/koog-comes-to-java/" class="btn" target="_blank">Explore Koog’s Java API</a>
                                                    </div>
                    </article>
                                    <article class="newsletter__post">
                                                                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="newsletter__post-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/04/sample-wasi-http-kotlin.webp" alt="Kotlin + WebAssembly: WASI HTTP sample">
                                                                            <div class="newsletter__post-text">
                                                            <h3>Kotlin + WebAssembly: `wasi:http` sample</h3>
                                                        <p>I like this sample because it shows how to run a minimal HTTP server with Kotlin and WebAssembly using `wasi:http`. It highlights practical progress in Kotlin’s WebAssembly story and future backend possibilities.</p>
                                                            <a href="https://github.com/Kotlin/sample-wasi-http-kotlin/" class="btn" target="_blank" rel="noopener">See the sample</a>
                                                    </div>
                    </article>
                                    <article class="newsletter__post">
                                                                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="newsletter__post-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/AMP-social-BlogSocialShare-1280x720-1.png" alt="">
                                                                            <div class="newsletter__post-text">
                                                            <h3>Amper 0.10.0</h3>
                                                        <p>Amper keeps evolving quickly, and this update brings several useful improvements. Version 0.10.0 introduces automatic JDK provisioning, a Maven-to-Amper converter, support for custom Kotlin compiler plugins, and an improved IDE experience.</p>
                                                            <a href="https://blog.jetbrains.com/amper/2026/03/amper-0-10/" class="btn" target="_blank">See what’s new in Amper 0.10.0</a>
                                                    </div>
                    </article>
                                    <article class="newsletter__post">
                                                                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="newsletter__post-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/IJ-social-BlogFeatured-1280x720-1-4.png" alt="">
                                                                            <div class="newsletter__post-text">
                                                            <h3>Spring Data JPA with Kotlin</h3>
                                                        <p>I found this practical post worthwhile because it shows how Spring Data JPA works with Kotlin across entities, repositories, custom queries, and DTOs. It is useful for teams already using Spring.</p>
                                                            <a href="https://blog.jetbrains.com/idea/2026/03/using-spring-data-jpa-with-kotlin" class="btn" target="_blank">Read the post</a>
                                                    </div>
                    </article>
                                    <article class="newsletter__post">
                                                                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="newsletter__post-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/04/spring.webp" alt="">
                                                                            <div class="newsletter__post-text">
                                                            <h3>Spring guide: Uploading Files</h3>
                                                        <p>This guide is helpful if you want to compare Kotlin and Java side by side. It makes it easier to see how Kotlin fits into existing backend workflows.</p>
                                                            <a href="https://spring.io/guides/gs/uploading-files" class="btn" target="_blank" rel="noopener">View the guide</a>
                                                    </div>
                    </article>
                                    <article class="newsletter__post">
                                                                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="newsletter__post-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/04/Coroutines-Race.webp" alt="">
                                                                            <div class="newsletter__post-text">
                                                            <h3>Coroutines Guesser Game</h3>
                                                        <p>Created by kt.academy, Coroutines Races Guesser Game offers an interactive approach to learning coroutine behavior by predicting what happens and when. It is a fun way to test your intuition.</p>
                                                            <a href="https://game.kt.academy/?game=coroutines" class="btn" target="_blank" rel="noopener">Play the game</a>
                                                    </div>
                    </article>
                                    </div>
    


<h2 class="wp-block-heading">Where you can learn more</h2>



<ul>
<li><a href="https://kotlinconf.com/workshops/" target="_blank" rel="noreferrer noopener">Workshops – KotlinConf 2026, May 20–22, Munich</a></li>



<li><a href="https://blog.jetbrains.com/ai/2026/04/using-acp-deep-agents-to-demystify-modern-software-engineering-2/" target="_blank" rel="noreferrer noopener">Introducing the Skill Manager and Skill Repository</a></li>



<li><a href="https://blog.jetbrains.com/ai/2026/04/give-ai-something-worth-amplifying-three-priorities-for-technical-leaders/" target="_blank" rel="noreferrer noopener">Give AI Something Worth Amplifying: Three Priorities for Technical Leaders</a></li>



<li><a href="https://blog.jetbrains.com/ai/2026/04/using-acp-deep-agents-to-demystify-modern-software-engineering/" target="_blank" rel="noreferrer noopener">Using ACP + Deep Agents to Demystify Modern Software Engineering</a></li>



<li><a href="https://gist.github.com/nomisRev/69d303615d967a1d35b74fb0f4df3b69" target="_blank" rel="noopener">Prototype LLM calls on the JVM using Kotlin Notebook and LangChain4j in IntelliJ IDEA</a></li>



<li><a href="https://blog.jetbrains.com/kotlin/2026/04/next-level-observability-with-opentelemetry/" target="_blank" rel="noreferrer noopener">Next-Level Observability with OpenTelemetry</a></li>



<li><a href="https://www.jetbrains.com/help/exposed/home.html" target="_blank" rel="noreferrer noopener">Exposed now supports array types out of the box for PostgreSQL</a></li>



<li><a href="https://blog.jetbrains.com/idea/2026/04/using-spring-data-jdbc-with-kotlin/" target="_blank" rel="noreferrer noopener">Using Spring Data JDBC With Kotlin</a></li>



<li><a href="https://ktor.io/changelog/3.4/" target="_blank" rel="noreferrer noopener">Ktor 3.4.3 has been released</a></li>



<li><a href="https://github.com/Kotlin/dokka/releases/tag/v2.2.0" target="_blank" rel="noopener">Dokka 2.2.0 is o</a><a href="https://github.com/Kotlin/dokka/releases/tag/v2.2.0" target="_blank" rel="noreferrer noopener">u</a><a href="https://github.com/Kotlin/dokka/releases/tag/v2.2.0" target="_blank" rel="noopener">t</a></li>
</ul>



<h2 class="wp-block-heading">YouTube highlights</h2>



<ul>
<li><a href="https://www.youtube.com/watch?v=nUzcVw5Kv20&amp;t=218s" target="_blank" rel="noreferrer noopener">How KMP Helped a 378-Year-Old Company</a></li>



<li><a href="https://www.youtube.com/watch?v=VJU0rygO03A" target="_blank" rel="noreferrer noopener">How Uber Uses AI to Move from Java to Kotlin</a></li>



<li><a href="https://youtu.be/5k-jh24CDZw?si=mmh297lrOkftPvae" target="_blank" rel="noreferrer noopener">Exposed 1.0 and Beyond | Talking Kotlin</a></li>



<li><a href="https://youtu.be/RZgd8N429bQ?si=6xwzAdWBN8eMbOzs" target="_blank" rel="noreferrer noopener">Best KMP libraries with Klibs.io</a></li>
</ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Next-Level Observability with OpenTelemetry</title>
		<link>https://blog.jetbrains.com/kotlin/2026/04/next-level-observability-with-opentelemetry/</link>
		
		<dc:creator><![CDATA[Viliam Sedliak]]></dc:creator>
		<pubDate>Wed, 29 Apr 2026 11:05:47 +0000</pubDate>
		<featuredImage>https://blog.jetbrains.com/wp-content/uploads/2026/04/KT-social-BlogFeatured-1280x720-1-5.png</featuredImage>		<category><![CDATA[kotlin]]></category>
		<category><![CDATA[news]]></category>
		<category><![CDATA[tutorials]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[backend]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[tutorial]]></category>
		<guid isPermaLink="false">https://blog.jetbrains.com/?post_type=kotlin&#038;p=703427</guid>

					<description><![CDATA[This tutorial was written by an external contributor. As a developer, logging is usually the first technique that you reach for when something goes wrong in your application. You add a few log statements at the start and end of a function and in the exception handlers, and then you get a basic picture of [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p><em>This tutorial was written by an external contributor.</em></p>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/04/58376469.png" alt="Kevin Kimani" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Kevin Kimani</h4>
                                                <p>Kevin Kimani is a software engineer and technical writer with over three years of experience in software development and documentation. He works across full-stack web development, database design, RESTful API development, and technical writing for engineer audiences. His writing focuses on clear API documentation, tutorials, and how-to guides that help developers understand and use products more easily.</p>
<p><a href="https://github.com/kimanikevin254" target="_blank" rel="noopener">GitHub</a> | <a href="https://x.com/KayveTech" target="_blank" rel="noopener">X.com</a></p>
                    </div>
                            </div>
        </div>
    </div>


            <div class="newsletter">
                                                            <article class="newsletter__post">
                                                                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="newsletter__post-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/04/KT-social-BlogFeatured-1280x720-1-4.png" alt="Repository with the companion code for the tutorial">
                                                                            <div class="newsletter__post-text">
                                                            <h3>Repository with the companion code for the tutorial</h3>
                                                                                                                    <a href="https://kotl.in/q0tysp" class="btn" target="_blank" rel="noopener">Go to GitHub</a>
                                                    </div>
                    </article>
                                    </div>
    


<p>As a developer, logging is usually the first technique that you reach for when something goes wrong in your application. You add a few log statements at the start and end of a function and in the exception handlers, and then you get a basic picture of what your application is doing. For simple services that run on a single instance, this approach is usually enough. You can just go through the log file, spot the error, and trace it back to its cause in just a few minutes.</p>



<p>But as your systems grow, that same approach doesn&#8217;t work. Logs start to pile up from multiple sources, executions interleave, and the error you&#8217;re looking at in the logs doesn&#8217;t provide enough information. You can clearly see the error, but you can&#8217;t trace it back to what caused it.<br><br>In this tutorial, you&#8217;ll learn how to move beyond basic logging by instrumenting a <a href="https://kotlinlang.org/docs/server-overview.html" target="_blank" rel="noreferrer noopener">Kotlin</a> and <a href="https://spring.io/projects/spring-boot" target="_blank" rel="noreferrer noopener">Spring Boot</a> backend service with <a href="https://opentelemetry.io/" target="_blank" rel="noreferrer noopener">OpenTelemetry</a>. You&#8217;ll learn how OpenTelemetry&#8217;s tracing model gives you the execution context that logs alone can&#8217;t provide. By the end of this guide, you&#8217;ll have a working instrumented service and a clear mental model for building more observable backend systems.</p>



<h2 class="wp-block-heading">Why You Need Next-Level Observability</h2>



<p>Modern backend systems are rarely linear. One operation might fan out to several downstream services, retry on failure, or execute concurrently across multiple instances and threads. All these patterns create opportunities for failure that might be hard to explain after the fact. When a background job that processes hundreds of records across overlapping executions errors out, your logs won&#8217;t tell you much. <strong>You won&#8217;t be able to explain which execution the error belonged to</strong> or whether the other executions succeeded or failed in the same way.</p>



<p>The lack of execution context creates a gap between seeing the error in your logs and actually understanding what happened leading to it. You just have the error message and a timestamp, but no way to connect it to the broader execution that it belongs to. In a system that runs multiple concurrent job executions, logs from different runs always interleave freely, and thread names get reused by the thread pool. Without a way to uniquely identify each execution, each line of text in your log file is an isolated fact without any reliable way to group it with others that belong to the same run.</p>



<p>Observability gives you a structured view of what your system did and in what order. It does this through traces, which are records of complete operations that contain unique identifiers. You can easily filter your logs by these trace identifiers, and <strong>you&#8217;ll be able to see the entire history of a specific execution clearly</strong>. Metrics add another dimension by revealing patterns over time that no single log entry can show. Together, they help to transform debugging from guesswork into a structured investigation.</p>



<h2 class="wp-block-heading">What OpenTelemetry Provides</h2>



<p>OpenTelemetry is an open-source observability framework that defines a unified model for collecting three types of signals from your applications:</p>



<ul>
<li><a href="https://opentelemetry.io/docs/concepts/signals/traces/" target="_blank" rel="noreferrer noopener"><strong>Traces</strong></a><strong>:</strong> represent the full lifecycle of a request or an operation as it moves through your system. A trace is made up of <a href="https://opentelemetry.io/docs/concepts/signals/traces/#spans" target="_blank" rel="noreferrer noopener">spans</a>, where each span represents a unit of work within the operation, such as an HTTP call or a background task. Each span contains a trace ID and a span ID as part of its context, where the trace ID ties back the span to its parent operation (trace) and the span ID uniquely identifies the single specific step within the operation.</li>



<li><a href="https://opentelemetry.io/docs/concepts/signals/metrics/" target="_blank" rel="noreferrer noopener"><strong>Metrics</strong></a><strong>:</strong> capture aggregated measurements over time, such as how long an operation takes and the error rates. This helps to give you a statistical view of the overall system health. <a href="https://opentelemetry.io/docs/concepts/signals/logs/" target="_blank" rel="noopener">&nbsp;</a></li>



<li><a href="https://opentelemetry.io/docs/concepts/signals/logs/" target="_blank" rel="noreferrer noopener"><strong>Logs</strong></a><strong>:</strong> represent discrete events that happened at a specific point in time. When correlated with trace context, logs stop being isolated entries in a file and become anchored events within a specific execution, which makes it easy to understand exactly what happened and why.<br></li>
</ul>



<p>The OpenTelemetry ecosystem consists of three main <a href="https://opentelemetry.io/docs/concepts/components/" target="_blank" rel="noreferrer noopener">components</a>:</p>



<ul>
<li>Instrumentation</li>



<li>The Collector</li>



<li>Exporters<br></li>
</ul>



<p>Instrumentation is how you integrate OpenTelemetry into your application. It uses language-specific SDKs that implement the OpenTelemetry API for creating spans, recording metrics, and propagating the context.</p>



<p>The <a href="https://opentelemetry.io/docs/collector/" target="_blank" rel="noreferrer noopener">Collector</a> is an optional but powerful middleware component that defines the logic for receiving, processing, and exporting telemetry data to one or more supported backends.</p>



<p>The exporters are plugins that send your application&#8217;s telemetry data to a specific destination, such as <a href="https://prometheus.io/" target="_blank" rel="noreferrer noopener">Prometheus</a>, <a href="https://jaegertracing.io/" target="_blank" rel="noreferrer noopener">Jaeger</a>, or any other compatible backend.</p>



<p>What makes OpenTelemetry a valuable long-term observability strategy is its vendor neutrality. Before OpenTelemetry, instrumentation was tightly coupled to specific vendors, and switching always meant that you needed to rewrite your instrumentation code throughout the entire codebase. OpenTelemetry fixed this by separating the instrumentation from the destination. This means that you can now instrument your service once using the standard API and then change the exporters as your infrastructure and specific requirements evolve.</p>


            <div class="newsletter">
                                                            <article class="newsletter__post">
                                                                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="newsletter__post-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/04/KT-social-BlogFeatured-1280x720-1-4.png" alt="Repository with the companion code for the tutorial">
                                                                            <div class="newsletter__post-text">
                                                            <h3>Repository with the companion code for the tutorial</h3>
                                                                                                                    <a href="https://kotl.in/e4s8j5" class="btn" target="_blank" rel="noopener">Go to GitHub</a>
                                                    </div>
                    </article>
                                    </div>
    


<h2 class="wp-block-heading">Setting Up Next-Level Observability with OpenTelemetry</h2>



<p>If you want to follow along with this tutorial, you&#8217;ll need the following:</p>



<ul>
<li>An IDE, such as<a href="https://www.jetbrains.com/idea/" target="_blank" rel="noreferrer noopener"> IntelliJ IDEA</a>.</li>



<li><a href="https://www.oracle.com/africa/java/technologies/downloads/" target="_blank" rel="noreferrer noopener">JDK 17 or later</a> and <a href="https://git-scm.com/book/en/v2/Getting-Started-Installing-Git" target="_blank" rel="noreferrer noopener">Git CLI</a> installed on your local machine.<br></li>
</ul>



<p>Here is a rough architecture diagram of what you’ll build in this guide:</p>



<figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" fetchpriority="high" src="https://blog.jetbrains.com/wp-content/uploads/2026/04/I5N8NCy.png" alt="" class="wp-image-703428" /></figure>



<p>The application consists of a Spring Boot Service running in a single Java Virtual Machine (JVM). The Task Scheduler triggers the <code>OrderSummaryJob</code> at regular intervals. The job reads orders from an embedded H2 database via Spring Data JPA, processes them, and writes summaries back to the database. The OpenTelemetry Java Agent sits within the JVM, automatically instrumenting the job and injecting trace context into the Mapped Diagnostic Context (MDC). This context flows through the log output, allowing you to correlate all logs from a single execution when multiple executions run concurrently.</p>



<p>Now that you have the prerequisites and understand the system you will build, it&#8217;s time to get started.</p>



<h3 class="wp-block-heading"><strong>Setting Up the Starter Template</strong></h3>



<p>To keep this tutorial focused on adding observability, we&#8217;ve prepared a Kotlin and Spring Boot application that runs a scheduled job every few minutes. Clone the application to your local machine by executing the following command:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">git clone --single-branch -b starter-template https://github.com/kimanikevin254/jetbrains-otel-order-summary.git</pre>



<p>Then, open the project in your code editor.</p>



<p>The most important file in this project is the <code>src/main/kotlin/com/example/order_summary/service/OrderSummaryJob.kt</code>, which defines the scheduled job. The job reads orders created in the last 24 hours from an <a href="https://www.h2database.com/html/main.html" target="_blank" rel="noreferrer noopener">H2</a> <a href="https://www.h2database.com/html/main.html" target="_blank" rel="noreferrer noopener">database</a> via Spring Data repositories, processes them one by one, and writes summaries back to the DB. The job runs every five minutes using Spring&#8217;s <code>@Scheduled</code> annotation. The summaries generated by this job can later be consumed by other parts of a larger system, such as dashboards, analytic pipelines, or downstream services that need a periodic snapshot of order volume and revenue.</p>



<p>Since this tutorial&#8217;s main focus is on observability, let&#8217;s review the logging approach used in this job:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Service
class OrderSummaryJob(
   private val orderRepository: OrderRepository,
   private val orderSummaryRepository: OrderSummaryRepository
) {
   private val logger = LoggerFactory.getLogger(OrderSummaryJob::class.java)

   @Scheduled(fixedDelay = 300000) // 5mins in ms
   fun generateSummary() {
       logger.info("Starting order summary job...")

       val periodEnd = LocalDateTime.now()
       val periodStart = periodEnd.minusHours(24)

       val orders = orderRepository.findByCreatedAtAfter(periodStart)
       if (orders.isEmpty()) {
           logger.info("No orders found in the last 24 hours. Skipping summary generation.")
           return
       }
       logger.info("Found ${orders.size} orders to process")

       var processedCount = 0
       var totalAmount = BigDecimal.ZERO

       for (order in orders) {
           try {
               logger.info("Processing order ${order.id} for customer ${order.customerId}...")

               // Simulate processing work
               Thread.sleep(2000)

               // Simulate occasional failures
               if (order.amount &gt; BigDecimal("400")) {
                   throw RuntimeException("Order amount exceeds threshold: ${order.amount}")
               }

               totalAmount = totalAmount.add(order.amount)
               processedCount++
           } catch (e: Exception) {
               logger.error("Failed to process order ${order.id}: ${e.message}")
               // Continue processing other orders
           }
       }

       val summary = OrderSummary(
           totalOrders = orders.size,
           totalAmount = totalAmount,
           periodStart = periodStart,
           periodEnd = periodEnd
       )

       orderSummaryRepository.save(summary)
       logger.info("Order summary job completed. Total: ${orders.size} orders, Amount $totalAmount")
   }
}</pre>



<p>As you can see, the logging approach is straightforward and very common. You log when the job starts, log each order being processed, log if an exception occurs, and log when the job finishes.</p>



<p>To see it in action, run the following command in your terminal:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">./gradlew bootRun</pre>



<p>Once the application starts, you can see the logs. Execute the command <code>tail -f logs/order-summary.log</code> in a separate terminal to stream the logs from the configured log file:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">2026-02-24T15:49:47.304+03:00  INFO 605417 --- [order-summary] [scheduling-1] c.e.o.service.OrderSummaryJob            : Found 12 orders to process
2026-02-24T15:49:47.305+03:00  INFO 605417 --- [order-summary] [scheduling-1] c.e.o.service.OrderSummaryJob            : Processing order 1 for customer CUST-10001...
2026-02-24T15:49:49.306+03:00  INFO 605417 --- [order-summary] [scheduling-1] c.e.o.service.OrderSummaryJob            : Processing order 3 for customer CUST-10003...
2026-02-24T15:49:51.307+03:00  INFO 605417 --- [order-summary] [scheduling-1] c.e.o.service.OrderSummaryJob            : Processing order 7 for customer CUST-10007...
2026-02-24T15:49:53.308+03:00  INFO 605417 --- [order-summary] [scheduling-1] c.e.o.service.OrderSummaryJob            : Processing order 8 for customer CUST-10008...
2026-02-24T15:49:55.308+03:00  INFO 605417 --- [order-summary] [scheduling-1] c.e.o.service.OrderSummaryJob            : Processing order 9 for customer CUST-10009...
2026-02-24T15:49:57.310+03:00 ERROR 605417 --- [order-summary] [scheduling-1] c.e.o.service.OrderSummaryJob            : Failed to process order 9: Order amount exceeds threshold: 458.23
...

2026-02-24T15:50:11.322+03:00 ERROR 605417 --- [order-summary] [scheduling-1] c.e.o.service.OrderSummaryJob            : Failed to process order 19: Order amount exceeds threshold: 427.98
2026-02-24T15:50:11.340+03:00  INFO 605417 --- [order-summary] [scheduling-1] c.e.o.service.OrderSummaryJob            : Order summary job completed. Total: 12 orders, Amount 1680.31</pre>



<p>The logs show clean, linear execution. Each step follows the previous one, and errors are easy to associate with the work being performed. This works well when the job runs infrequently, and only a single instance of the application is deployed. One execution completes before the next begins, so tracing failures back to their source is straightforward. For early-stage systems, this level of logging is sufficient.</p>



<h3 class="wp-block-heading">Introducing Complexity</h3>



<p>As a project evolves, two changes might occur:</p>



<ul>
<li>The business might demand near real-time visibility into the order metrics, which means that the job needs to run more frequently. Say, every five seconds instead of every five minutes.</li>



<li>The application may be deployed across multiple instances for high availability.<br></li>
</ul>



<p>Let&#8217;s start by running the job more frequently to see how this affects our current logging approach. To do this, open the <code>src/main/kotlin/com/example/order_summary/OrderSummaryApplication.kt</code> file and add the following line of code to the main application class:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@EnableAsync</pre>



<p>This enables async execution. Remember to add the following import statement to the same file:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import org.springframework.scheduling.annotation.EnableAsync</pre>



<p>Next, open the <code>src/main/kotlin/com/example/order_summary/service/OrderSummaryJob.kt</code> file and replace <code>@Scheduled(fixedDelay = 300000) // 5mins</code> with the following:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Async
@Scheduled(fixedRate = 5000) // 5secs in ms</pre>



<p>Changing from <code>fixedDelay</code> to <code>fixedRate</code> means the job starts every five seconds regardless of whether the previous execution has finished. Adding <code>@Async</code> ensures that each execution runs on its own thread from Spring&#8217;s task executor pool, preventing slow jobs from blocking the scheduler. This is a common pattern when scaling background jobs to handle higher throughput.<br><br>Remember to add the following import statement to the same file:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@import org.springframework.scheduling.annotation.Async</pre>



<p>Restart the application and observe the logs. You should see something like this:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">2026-02-24T16:17:40.469+03:00  INFO 610799 --- [order-summary] [task-1] c.e.o.service.OrderSummaryJob            : Starting order summary job...
2026-02-24T16:17:40.596+03:00  INFO 610799 --- [order-summary] [task-1] c.e.o.service.OrderSummaryJob            : Found 12 orders to process
2026-02-24T16:17:40.597+03:00  INFO 610799 --- [order-summary] [task-1] c.e.o.service.OrderSummaryJob            : Processing order 1 for customer CUST-10001...
...
2026-02-24T16:17:47.468+03:00  INFO 610799 --- [order-summary] [task-2] c.e.o.service.OrderSummaryJob            : Processing order 3 for customer CUST-10003...
2026-02-24T16:17:48.602+03:00  INFO 610799 --- [order-summary] [task-1] c.e.o.service.OrderSummaryJob            : Processing order 9 for customer CUST-10009...
2026-02-24T16:17:49.469+03:00  INFO 610799 --- [order-summary] [task-2] c.e.o.service.OrderSummaryJob            : Processing order 7 for customer CUST-10007...
2026-02-24T16:17:50.460+03:00  INFO 610799 --- [order-summary] [task-3] c.e.o.service.OrderSummaryJob            : Starting order summary job...
2026-02-24T16:17:50.472+03:00  INFO 610799 --- [order-summary] [task-3] c.e.o.service.OrderSummaryJob            : Found 12 orders to process
2026-02-24T16:17:50.473+03:00  INFO 610799 --- [order-summary] [task-3] c.e.o.service.OrderSummaryJob            : Processing order 1 for customer CUST-10001...
...
2026-02-24T16:17:54.476+03:00  INFO 610799 --- [order-summary] [task-3] c.e.o.service.OrderSummaryJob            : Processing order 7 for customer CUST-10007...
2026-02-24T16:17:54.608+03:00  INFO 610799 --- [order-summary] [task-1] c.e.o.service.OrderSummaryJob            : Processing order 14 for customer CUST-10014...
2026-02-24T16:17:55.460+03:00  INFO 610799 --- [order-summary] [task-4] c.e.o.service.OrderSummaryJob            : Starting order summary job...
2026-02-24T16:17:55.473+03:00  INFO 610799 --- [order-summary] [task-4] c.e.o.service.OrderSummaryJob            : Found 12 orders to process
2026-02-24T16:17:55.474+03:00  INFO 610799 --- [order-summary] [task-4] c.e.o.service.OrderSummaryJob            : Processing order 1 for customer CUST-10001...
2026-02-24T16:17:55.475+03:00 ERROR 610799 --- [order-summary] [task-2] c.e.o.service.OrderSummaryJob            : Failed to process order 9: Order amount exceeds threshold: 458.23</pre>



<p>The logs are now completely interleaved. Executions from <code>task-1</code>, <code>task-2</code>, and <code>task-3</code> are all running simultaneously, processing the orders, and logging to the same output. When an error occurs, like the failure on order 9 at 16:17:55, it&#8217;s not easy to figure out which job execution the log belongs to and which orders were successfully processed before the error occurred in that specific execution.</p>



<p>You might think searching by thread name, such as <code>task-1</code>, would solve this, but Spring&#8217;s thread pool reuses threads. After <code>task-1</code> finishes its first execution, it picks up execution 9, then execution 17, and so on. Searching by thread name now gives you mixed logs from multiple unrelated executions. In production, where multiple application instances run behind a load balancer, thread names are no longer unique across your system.</p>



<p>This is where plain logging breaks down. You know and see that something failed, but you can&#8217;t explain what happened leading up to it.</p>



<h3 class="wp-block-heading"><strong>A Better Solution: Adding OpenTelemetry</strong></h3>



<p>To address the missing execution context, let&#8217;s adapt the application to use OpenTelemetry for log correlation. The goal is not to analyze the performance or optimize the job, but to fix the issue of associating logs with their execution context. Each job execution will be treated as a logical unit of work. A unique trace ID will be attached to that execution, and all logs emitted during the job will include that ID. This way, even when multiple executions run concurrently, and your logs get interleaved, you can filter them by trace ID and see exactly what happened in a single run from the start to the end.</p>



<p>OpenTelemetry provides <a href="https://opentelemetry.io/docs/languages/java/instrumentation/#instrumentation-categories" target="_blank" rel="noreferrer noopener">several ways</a> to instrument applications. In this guide, we&#8217;ll use the <a href="https://opentelemetry.io/docs/zero-code/java/agent/" target="_blank" rel="noreferrer noopener">Java Agent</a>, which automatically instruments your application without requiring any changes to the source code.</p>



<p>Let&#8217;s start by downloading the agent JAR file. Execute the following commands in the project root folder to create a directory for the agent and download it:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">mkdir -p agents
curl -L https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar \
-o agents/opentelemetry-javaagent.jar</pre>



<p>Verify the download using the following command:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">ls -lh agents/opentelemetry-javaagent.jar</pre>



<p>You should see a file around 24MB in size.</p>



<p>Add the <code>agents/</code> directory to your <code>.gitignore</code> file so that the JAR file is not committed to version control. You can use the command <code>echo "agents/" &gt;&gt; .gitignore</code> or add it manually. <br><br>Once you&#8217;ve confirmed that the agent was downloaded successfully, it&#8217;s time to configure it. You need to attach it to the JVM when running the application by passing it as an argument. Open the <code>build.gradle.kts</code> file and add the following configuration:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">tasks.bootRun {
   jvmArgs = listOf(
       "-javaagent:${projectDir}/agents/opentelemetry-javaagent.jar",
       "-Dotel.service.name=order-summary-service",
       "-Dotel.traces.exporter=logging",
       "-Dotel.metrics.exporter=none",
       "-Dotel.logs.exporter=none"
   )
}</pre>



<p>Here is what each argument does:</p>



<ul>
<li><code>-javaagent</code> tells the JVM to load the OpenTelemetry agent before your application starts</li>



<li><code>-Dotel.service.name</code> sets the name of your service in the telemetry data</li>



<li><code>-Dotel.traces.exporter=logging</code> prints trace data to the console. No external backend is needed for this guide</li>



<li><code>-Dotel.metrics.exporter=none</code> and <code>-Dotel.logs.exporter=none</code> disable metrics and log exporting since that is outside the scope of this guide<br></li>
</ul>



<p>Lastly, you need to update the log patterns to include trace context. The OpenTelemetry agent automatically injects <code>trace_id</code> and <code>span_id</code> into the logging context (Mapped Diagnostic Context). To display these values in your application logs, open the <code>src/main/resources/application.properties</code> file and add the following:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">logging.pattern.console=%d{HH:mm:ss.SSS} [%thread] [trace_id=%mdc{trace_id} span_id=%mdc{span_id}] %-5level %logger{36} - %msg%n
logging.pattern.file=%d{HH:mm:ss.SSS} [%thread] [trace_id=%mdc{trace_id} span_id=%mdc{span_id}] %-5level %logger{36} - %msg%n</pre>



<p>The <code>%mdc{trace_id}</code> and <code>%mdc{span_id}</code> directives extract values from the MDC that the agent populates automatically.</p>



<p>Now, let&#8217;s restart the application and observe the logs:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">17:19:43.715 [task-1] [trace_id=da673f1ec49eba77264c5912584e7183 span_id=74c708e335a974e3] INFO  c.e.o.service.OrderSummaryJob - Starting order summary job...
17:19:43.856 [task-1] [trace_id=da673f1ec49eba77264c5912584e7183 span_id=74c708e335a974e3] INFO  c.e.o.service.OrderSummaryJob - Found 12 orders to process
17:19:43.857 [task-1] [trace_id=da673f1ec49eba77264c5912584e7183 span_id=74c708e335a974e3] INFO  c.e.o.service.OrderSummaryJob - Processing order 1 for customer CUST-10001...
17:19:45.860 [task-1] [trace_id=da673f1ec49eba77264c5912584e7183 span_id=74c708e335a974e3] INFO  c.e.o.service.OrderSummaryJob - Processing order 3 for customer CUST-10003...

...

17:19:53.704 [task-3] [trace_id=4a969bbb00634e0ee36b2fbda1399d8a span_id=0a602f1a58df2f71] INFO  c.e.o.service.OrderSummaryJob - Starting order summary job...
17:19:53.715 [task-3] [trace_id=4a969bbb00634e0ee36b2fbda1399d8a span_id=0a602f1a58df2f71] INFO  c.e.o.service.OrderSummaryJob - Found 12 orders to process
17:19:53.715 [task-3] [trace_id=4a969bbb00634e0ee36b2fbda1399d8a span_id=0a602f1a58df2f71] INFO  c.e.o.service.OrderSummaryJob - Processing order 1 for customer CUST-10001...
17:19:53.868 [task-1] [trace_id=da673f1ec49eba77264c5912584e7183 span_id=74c708e335a974e3] ERROR c.e.o.service.OrderSummaryJob - Failed to process order 9: Order amount exceeds threshold: 458.23</pre>



<p>All logs from the first execution share the same <code>trace_id</code> (<code>da673f1ec49eba77264c5912584e7183</code>), while logs from the third execution have a different <code>trace_id</code> (<code>4a969bbb00634e0ee36b2fbda1399d8a</code>). Even though both executions are running concurrently and their logs are interleaved, you can now filter by trace ID to isolate a single execution.</p>



<p>For example, to see logs only from the first execution, you could search for <code>trace_id=da673f1ec49eba77264c5912584e7183</code> in a log aggregation tool such as<a href="https://aws.amazon.com/cloudwatch/" target="_blank" rel="noreferrer noopener"> Amazon CloudWatch</a>.</p>



<p>All the code used in this tutorial is available on <a href="https://github.com/kimanikevin254/jetbrains-otel-order-summary" target="_blank" rel="noreferrer noopener">GitHub</a>.</p>



<h3 class="wp-block-heading">Future Considerations</h3>



<p>To make filtering even more powerful, you can update this logging strategy further by adding structured fields to logs for record IDs or job phases. For example, you could log <code>order_id</code> as a dedicated field alongside the trace ID, allowing you to query all executions that touched a specific order.</p>



<p>You can also export logs alongside traces to an observability backend like <a href="https://jaegertracing.io/" target="_blank" rel="noreferrer noopener">Jaeger</a> or<a href="https://grafana.com/" target="_blank" rel="noreferrer noopener"> Grafana</a>. This allows you to visualize the full trace as a timeline, showing how long each step took and where errors occurred. The OpenTelemetry agent supports exporting to multiple backends by changing the exporter configuration, so you can start with logging and migrate to a full observability platform later without making any changes to your instrumentation code.</p>



<p>You can also apply this same pattern to other background jobs, API handlers, or any asynchronous work in your system. Once OpenTelemetry is in place, every part of your application automatically benefits from trace context propagation, making it easier to debug complex workflows that span multiple services or components.</p>



<h2 class="wp-block-heading"><strong>Conclusion</strong></h2>



<p>In this guide, you built a Kotlin and Spring Boot application with a scheduled background job, observed how plain logging breaks down under concurrency, and solved the problem by instrumenting the application with OpenTelemetry. You learned how the OpenTelemetry Java Agent automatically injects trace context into logs without requiring code changes, and how trace IDs enable you to correlate logs from a single execution even when multiple executions run concurrently.</p>



<p>Observability isn&#8217;t just about adding more logs; it&#8217;s about adding structure and context to the signals your system already emits. With OpenTelemetry, you can turn interleaved, confusing logs into isolated, queryable execution traces.</p>



<p>But the benefits go beyond debugging. Building systems with observability in mind changes how you design them. Traces reveal where boundaries should exist and help you set realistic timeouts based on actual production data. Metrics show trends over time, which make it easier to plan capacity, define SLOs, and alert on deviations before your users are affected. Additionally, well-instrumented code is more readable. When every operation is traced, you think more carefully about what constitutes a meaningful unit of work, which makes the system clearer for both observability tools and other developers.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Kotlin Professional Certificate by JetBrains – Now on LinkedIn Learning</title>
		<link>https://blog.jetbrains.com/kotlin/2026/04/kotlin-professional-certificate-by-jetbrains-now-on-linkedin-learning/</link>
		
		<dc:creator><![CDATA[Ksenia Shneyveys]]></dc:creator>
		<pubDate>Tue, 21 Apr 2026 13:21:36 +0000</pubDate>
		<featuredImage>https://blog.jetbrains.com/wp-content/uploads/2026/04/KT-social-BlogFeatured-1280x720-1-1.png</featuredImage>		<category><![CDATA[education]]></category>
		<category><![CDATA[news]]></category>
		<guid isPermaLink="false">https://blog.jetbrains.com/?post_type=kotlin&#038;p=702390</guid>

					<description><![CDATA[JetBrains has partnered with LinkedIn Learning to offer the Kotlin Professional Certificate. This is a structured learning path that covers the full scope of modern software development – from Kotlin essentials all the way to building full-stack, multiplatform applications for mobile, desktop, web, and backend environments. Start Learning Who it’s for This certification is designed [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>JetBrains has partnered with LinkedIn Learning to offer the <a href="https://kotl.in/pro-cert-lil" target="_blank" rel="noreferrer noopener">Kotlin Professional Certificate</a>. This is a structured learning path that covers the full scope of modern software development – from Kotlin essentials all the way to building full-stack, multiplatform applications for mobile, desktop, web, and backend environments.</p>



<div class="buttons">
        <div class="buttons__row">
            <a class="ek-link jb-download-button" title="Start Learning" href="https://kotl.in/pro-cert-lil" target="_blank" rel="noopener" data-test="blog-article-cta" data-cl="true">Start Learning</a>
         </div>
</div>



<h1 class="wp-block-heading">Who it’s for</h1>



<p>This certification is designed for developers with basic programming knowledge who want to pick up Kotlin and explore multiplatform development. Whether you&#8217;re coming from Java, Python, C, or another language, this program will give you insight into what Kotlin can do across the full development landscape. If you are a mobile developer who wants to stop writing things twice, a backend developer curious about Kotlin’s server-side capabilities, or a generalist who wants to ship on multiple platforms without fracturing your codebase, this is for you.</p>



<h1 class="wp-block-heading">What the learning path covers</h1>



<p>The certification includes four courses structured to guide you along an intuitive path:</p>



<p><strong>Kotlin Essential Training: Functions, Collections, and I/O</strong> starts with the fundamentals – how Kotlin handles functions, how its collection APIs work, and how to interact with files and I/O, as well as core Kotlin syntax. If you are coming from Java, a lot of this will feel familiar but cleaner. If you are coming from elsewhere, this is where Kotlin’s expressiveness starts to click.</p>



<p><strong>Kotlin Essential Training: Object-Oriented and Async Code</strong> goes deeper into OOP principles and asynchronous programming in Kotlin. The course introduces distinctive Kotlin features such as sealed classes, data classes, and extension functions, while showing how coroutines make async programming more readable. This course builds the foundation you need before getting started with multiplatform.</p>



<p><strong>Kotlin Multiplatform Development</strong> teaches you how to write shared business logic once and deploy it across multiple platforms – mobile (Android and iOS), web, desktop, and backend. You’ll learn about the architecture that makes this possible, as well as how to structure a KMP project, what can and can’t be shared, and how to make the boundaries between platforms work for you rather than against you.</p>



<p><strong>Exploring Ktor With Kotlin and Compose Multiplatform</strong> brings it all together. Ktor is JetBrains&#8217; own framework for building asynchronous servers and clients in Kotlin; Compose Multiplatform extends Jetpack Compose to desktop and web. Together, they let you build full-stack applications with a genuinely unified approach. This course is the practical capstone – you leave with experience actually building something, not just learning concepts.</p>



<h1 class="wp-block-heading">Access</h1>



<p>The Kotlin Professional Certificate is available on <a href="https://www.linkedin.com/learning/paths/kotlin-professional-certificate-by-jetbrains?utm_source=blog&amp;utm_medium=referral&amp;utm_campaign=lil" target="_blank" rel="noreferrer noopener">LinkedIn Learning</a> through a LinkedIn Premium subscription, which includes a one-month free trial for eligible users. Many organizations and universities also provide LinkedIn Learning access to their employees and students, and some public libraries offer free access with a library card as well, so it&#8217;s worth checking with your employer or institution.</p>



<div class="buttons">
        <div class="buttons__row">
            <a class="ek-link jb-download-button" title="Start Learning" href="https://kotl.in/pro-cert-lil" target="_blank" rel="noopener" data-test="blog-article-cta" data-cl="true">Start Learning</a>
         </div>
</div>



<h1 class="wp-block-heading">The certificate</h1>



<p>In total, the certification takes about 11 hours spread across the four courses. You’ll work in IntelliJ IDEA, the industry’s leading IDE, gaining practical knowledge that’s essential for your career. By the end, you&#8217;ll be able to build complete multiplatform applications from a shared codebase.&nbsp;</p>



<p>Complete all four courses and pass the final exam to earn your Kotlin Professional Certificate by JetBrains. You’ll be able to download it, share it, and add it directly to your LinkedIn profile to showcase your Kotlin and multiplatform development skills to recruiters and hiring managers.</p>



<p>Let us know how you like the courses, and be sure to share your certificate and <a href="https://www.linkedin.com/company/jetbrains/" target="_blank" data-type="link" data-id="https://www.linkedin.com/company/jetbrains/" rel="noreferrer noopener">tag us</a> on LinkedIn.</p>



<p>We’re excited to see what you build with Kotlin!</p>
]]></content:encoded>
					
		
		
		                    <language>
                        <code><![CDATA[zh-hans]]></code>
                        <url>https://blog.jetbrains.com/zh-hans/kotlin/2026/04/kotlin-professional-certificate-by-jetbrains-now-on-linkedin-learning/</url>
                    </language>
                                    <language>
                        <code><![CDATA[ko]]></code>
                        <url>https://blog.jetbrains.com/ko/kotlin/2026/04/kotlin-professional-certificate-by-jetbrains-now-on-linkedin-learning/</url>
                    </language>
                	</item>
		<item>
		<title>Helping Decision-Makers Say Yes to Kotlin Multiplatform (KMP)</title>
		<link>https://blog.jetbrains.com/kotlin/2026/04/helping-decision-makers-say-yes-to-kmp/</link>
		
		<dc:creator><![CDATA[Ekaterina Volodko]]></dc:creator>
		<pubDate>Mon, 20 Apr 2026 14:39:57 +0000</pubDate>
		<featuredImage>https://blog.jetbrains.com/wp-content/uploads/2026/04/KM-social-BlogFeatured-1280x720-1.png</featuredImage>		<category><![CDATA[multiplatform]]></category>
		<category><![CDATA[kmp]]></category>
		<category><![CDATA[kotlin-multiplatform]]></category>
		<guid isPermaLink="false">https://blog.jetbrains.com/?post_type=kotlin&#038;p=697905</guid>

					<description><![CDATA[This post was written by external contributors from Touchlab. KMP is a strategic platform In the current competitive landscape, the traditional mobile development model characterized by maintaining independent, duplicated codebases for iOS and Android is no longer a sustainable use of capital. This approach systematically introduces feature lag, technical debt, and a fragmented engineering culture [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p><em>This post was written by external contributors from Touchlab</em>.</p>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/04/portrait.22b39ebb3064ee3e.webp" alt="Justin Mancinelli" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Justin Mancinelli</h4>
                                                <p>Justin Mancinelli is VP of Client Services at Touchlab, where he leads client services strategy and complex technical delivery. He partners with engineering leaders on mobile apps, SDKs, developer tooling, Kotlin Multiplatform, and Compose Multiplatform. With more than 13 years of experience helping software businesses succeed, he focuses on turning product and engineering goals into delivery.</p>
<p><a href="https://www.linkedin.com/in/justinmancinelli/" target="_blank" rel="noopener">LinkedIn</a></p>
                    </div>
                            </div>
        </div>
    </div>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/04/1756344765502.webp" alt="Samuel Hill from Touchlab" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Samuel Hill</h4>
                                                <p>As VP of Engineering at Touchlab, Samuel Hill leads engineering strategy and supports teams building mobile products across Android and iOS. He works with engineering leaders on Kotlin Multiplatform, architecture, development standards, and team growth. With more than 13 years of experience in mobile engineering, he focuses on strong technical delivery and cross-functional collaboration.</p>
<p><a href="https://www.linkedin.com/in/hillsamuel/" target="_blank" rel="noopener">LinkedIn</a></p>
                    </div>
                            </div>
        </div>
    </div>



<h2 class="wp-block-heading">KMP is a strategic platform</h2>



<p>In the current competitive landscape, the traditional mobile development model characterized by maintaining independent, duplicated codebases for iOS and Android is no longer a sustainable use of capital. This approach systematically introduces feature lag, technical debt, and a fragmented engineering culture that hinders organizational agility. For leadership, adopting <a href="https://kotlinlang.org/multiplatform/" target="_blank" rel="noopener">Kotlin Multiplatform (KMP)</a> must be viewed as a fundamental shift in capital allocation for mobile engineering.<br><br>KMP is not merely an incremental technical upgrade – it is a strategic platform that enables a unified engineering organization. By sharing high-value business logic while preserving native performance and UI integrity, KMP enables organizations to drastically reduce the total cost of ownership (TCO) of their mobile ecosystem. This transition transforms mobile development from platform-specific silos into a high-velocity engine that accelerates roadmaps, mitigates delivery risks, and secures a competitive advantage. As organizations increasingly integrate AI into their products, Kotlin Multiplatform provides a reliable, JVM-native foundation for building and deploying AI-powered mobile and backend services without introducing additional language or runtime complexity.</p>



<h2 class="wp-block-heading">Quantifiable metrics for KMP adoption</h2>



<p>Understanding the strategic impact of Kotlin Multiplatform for your organization starts with modeling potential cost savings, development velocity improvements, and risk mitigations. The following data, synthesized from enterprise-scale implementations and market leaders, provides an empirical foundation for proposing, budgeting, and planning your KMP adoption initiative.</p>


<figure class="wp-block-table is-style-stripes">
<table>
<thead>
<tr>
<th><strong>Advantage</strong></th>
<th><strong>Improved metrics</strong><sup>1</sup></th>
<th><strong>Business/team impact</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Code reduction</strong></td>
<td>40–60% less code<br />80% logic shared</td>
<td>Dramatic reduction in technical debt and long-term maintenance overhead</td>
</tr>
<tr>
<td><strong>Development velocity</strong></td>
<td>20-40% faster code reviews<br />15–30% faster release cycles</td>
<td>Increased bandwidth for senior talent and faster PR throughput</td>
</tr>
<tr>
<td><strong>Quality and reliability</strong></td>
<td>40–60% fewer bugs<br />25–40% fewer platform-specific edge cases</td>
<td>Reduced QA cycles and higher customer satisfaction through consistent behavior</td>
</tr>
<tr>
<td><strong>Timeline acceleration</strong></td>
<td>50% faster implementation<br />Multi-year roadmaps realized in a single quarter</td>
<td>Drastically shortened time-to-market makes it possible to respond to market shifts in real time and execute strategic pivots under urgent deadlines</td>
</tr>
<tr>
<td style="padding-top: 8px" colspan="3">
<p style="font-size: 90%">1. These figures were derived from proprietary and public data gathered from Touchlab clients and community case studies (see the <a href="#provenmarketvalidation"><em>Proven market validation</em></a> section for example data). Actual results may vary depending on architecture, team structure, and project scope.</p>
</td>
</tr>
</tbody>
</table>
</figure>


<h2 class="wp-block-heading">Velocity and feature parity</h2>



<p>KMP eliminates the feature lag that historically forces businesses to delay launching on the second platform and marketing departments to delay new feature announcements. In traditional siloed development, discrepancies in business logic and implementation speed between iOS and Android teams are inevitable. KMP solves this by enabling a single, verified implementation of business rules that serves both platforms simultaneously.</p>



<p>An engineer can build and test a new feature on one platform. Subsequent platforms then simply hook up the existing data models and logic from the shared KMP code to their native UI. This groundwork reuse ensures consistency from day one.&nbsp;</p>



<p>Beyond immediate speed, this unified architecture promotes maintainability and de-risks incremental development across platforms. Future requirements, such as top-down enforced migration from one data, analytics, or streaming platform to another, are accelerated by building upon a stable, shared foundation that supports synchronized launches across the entire user ecosystem.</p>



<h2 class="wp-block-heading">Organizational risk reduction</h2>



<p>Adopting KMP is a primary driver for organizational risk reduction, enforcing a new foundation that prioritizes architectural discipline over the spaghetti often found in legacy mobile apps. By centralizing core business logic, organizations gain strategic agility that de-risks the technical roadmap. This architectural flexibility allows leadership to pivot across web and mobile ecosystems at a speed impossible when logic is trapped in platform-specific silos, enabling the engineering department to meet sudden market demands.</p>



<p>Consolidating complex calculations and business rules into a single source of truth fundamentally lowers the probability of systemic error. When logic is duplicated across disparate codebases, an organization implicitly accepts a doubled risk of regression and a fractured quality assurance cycle. KMP mitigates this operational hazard by ensuring that a single, verified enhancement or fix propagates across the entire product line, effectively slashing the technical debt and remediation costs that typically compound in traditional multi-platform environments.</p>



<p>Shared logic with KMP naturally mandates a clean separation of concerns, moving the organization away from fragile, UI-entangled code. The clear architecture empowers teams to achieve significantly higher automated test coverage, which removes the fear of the unknown that often plagues legacy systems. As the codebase becomes more predictable and less reliant on manual intervention, the organization achieves a level of stability where innovation can occur without the constant threat of destabilizing critical business functions.</p>



<h2 class="wp-block-heading">Engineering culture and talent</h2>



<p>The shift to KMP directly affects talent retention and internal mobility within the engineering organization. By moving away from platform-specific constraints, KMP allows teams to transition from isolated silos to a unified model where developers function as mobile engineers. This shift creates a more flexible and responsive technical workforce where engineering resources are allocated based on business priorities rather than purely on platform and language expertise.</p>



<p>Architectural alignment simplifies the codebase and clarifies the path to productivity for new hires. By maintaining a single logic layer instead of two separate implementations, organizations typically see a 30–50% reduction in onboarding time. Engineers can focus on mastering a well-structured system that minimizes technical debt and cognitive overhead often found in siloed environments.</p>



<h2 class="wp-block-heading" id="provenmarketvalidation">Proven market validation</h2>



<p>KMP has proven its benefit at world-class organizations that require stability and scale. The following companies have been Touchlab clients, or discussed their data publicly with Touchlab and JetBrains:</p>



<ul>
<li><a href="https://engineering.block.xyz/blog/how-bitkey-uses-cross-platform-development" target="_blank" rel="noopener">Bitkey</a> shares 95% of its mobile codebase with KMP and was able to tear down silos so that Android and iOS engineers became mobile engineers, picking up tickets no matter the platform</li>



<li><a href="http://www.blackstonepublishing.com" target="_blank" rel="noopener">Blackstone</a> achieved a 50% increase in implementation speed within six months of code consolidation, sharing ~90% of business logic with KMP.</li>



<li><a href="https://www.youtube.com/watch?v=RJtiFt5pbfs" target="_blank" rel="noopener">Duolingo</a> saved 6–12 engineer-months leveraging KMP to deliver iOS and Web implementations after the initial Android implementation. They spent five engineer-months to adopt KMP and deliver the iOS version of Adventures, then only one and a half engineer-months to deliver it to web, leveraging the same KMP codebase compared to 9 months for the initial Android implementation.&nbsp;</li>



<li><a href="https://www.forbes.com/sites/forbes-engineering/2023/11/13/forbes-mobile-app-shifts-to-kotlin-multiplatform/" target="_blank" rel="noopener">Forbes</a> achieved significant savings in engineering time and effort by consolidating over 80% of logic across platforms, sharing ~90% of business logic in total.</li>



<li><a href="https://android-developers.googleblog.com/2024/05/android-support-for-kotlin-multiplatform-to-share-business-logic-across-mobile-web-server-desktop.html" target="_blank" rel="noopener">Google</a> has been investing in and transitioning to KMP for several years, stating that KMP allows for “flexibility and speed in delivering valuable cross-platform experiences”. The <a href="https://www.youtube.com/watch?v=5lkZj4v4-ks" target="_blank" rel="noopener">Google Workspace</a> team found that iOS runtime performance and app size with KMP were on par with those of the existing code.</li>



<li><a href="https://www.youtube.com/watch?v=hZPL8QqiLi8" target="_blank" rel="noopener">Philips</a> effectively halved the time to develop features on both Android and iOS.</li>



<li>An information security company re-targeted their mobile app to the web in three weeks for a press conference after a third-party vendor blocked the release of their mobile apps. Thanks to KMP, it was very easy to call the already implemented and tested code from JavaScript.</li>



<li>A national media company built its KMP Identity SDK for use across brand apps on Android, iOS, and web, with a team half the size of that typically allocated for platform-specific projects.</li>



<li>A world leader in tabletop gaming accelerated a multi-year mobile roadmap into a single quarter with KMP to meet the needs of explosive growth and demographic shift towards mobile users.<br></li>
</ul>



<p>For more stories discussing real-world strategies, integration approaches, and gains from KMP, check out the Kotlin Multiplatform case studies collected by JetBrains.</p>



<div class="buttons">
        <div class="buttons__row">
            <a class="ek-link jb-download-button" title="See KMP case studies" href="https://kotlinlang.org/case-studies/?type=multiplatform" target="_blank" rel="noopener" data-test="blog-article-cta" data-cl="true">See KMP case studies</a>
         </div>
</div>



<h2 class="wp-block-heading"><strong>Strategic recommendation</strong></h2>



<p>Kotlin Multiplatform is a future-proof architectural standard developed by JetBrains and supported by Google. It offers a low-risk, high-reward path for organizations looking to modernize their mobile strategy. Most organizations that adopt KMP for shared logic see a measurable ROI within three to six months.</p>



<p>The strategic recommendation is to initiate a pilot project focusing on pure business logic areas, such as calculations, data models, and business rules. With a conservative sharing potential of 75% in these areas, scaling KMP will allow your organization to eliminate redundant effort and transition toward a high-velocity, unified engineering future.</p>



<p><strong>The Touchlab acceleration factor:</strong> While the long-term gains of KMP are inherent to the technology, expert guidance from experienced Kotlin Multiplatform practitioners, such as Touchlab, can help minimize the initial learning curve and accelerate adoption. Specialized assistance early in the adoption process prevents the trial-and-error phase that can stall pilot projects, ensuring the first success occurs quickly and the architectural benefits begin compounding immediately. When scaling challenges arise, Touchlab’s tools and experience take your KMP teams to the next level. Find out what Touchlab can do for you at <a href="https://touchlab.co" target="_blank" rel="noopener">https://touchlab.co</a>.</p>
]]></content:encoded>
					
		
		
		                    <language>
                        <code><![CDATA[ko]]></code>
                        <url>https://blog.jetbrains.com/ko/kotlin/2026/04/helping-decision-makers-say-yes-to-kmp/</url>
                    </language>
                	</item>
		<item>
		<title>Introducing Koog Integration for Spring AI: Smarter Orchestration for Your Agents</title>
		<link>https://blog.jetbrains.com/ai/2026/04/introducing-koog-integration-for-spring-ai-smarter-orchestration-for-your-agents/</link>
		
		<dc:creator><![CDATA[Maria Tigina]]></dc:creator>
		<pubDate>Thu, 16 Apr 2026 14:01:57 +0000</pubDate>
		<featuredImage>https://blog.jetbrains.com/wp-content/uploads/2026/04/KG-social-BlogFeatured-1280x720-1-2.png</featuredImage>		<product ><![CDATA[kotlin]]></product>
		<guid isPermaLink="false">https://blog.jetbrains.com/?post_type=ai&#038;p=700794</guid>

					<description><![CDATA[Spring AI is the application-facing integration layer you may already use. Koog is the next layer up when you need agent orchestration. Spring AI already covers the chat model API, chat memory, and vector storage for RAG, and it provides Spring Boot starters with auto-configuration. Koog’s role is not to erase that, but rather to [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Spring AI is the application-facing integration layer you may already use. <a href="https://www.jetbrains.com/koog/" target="_blank" data-type="link" data-id="https://www.jetbrains.com/koog/" rel="noreferrer noopener">Koog</a> is the next layer up when you need agent orchestration. Spring AI already covers the chat model API, chat memory, and vector storage for RAG, and it provides Spring Boot starters with auto-configuration. Koog’s role is not to erase that, but rather to add a stronger agent runtime, offering:</p>



<ul>
<li>Multi-step strategies and workflows for more precise control.</li>



<li>Persistence and checkpoints for fault-tolerant execution.</li>



<li>Sophisticated history management for cost-optimization.</li>



<li>Automated deterministic planning.</li>
</ul>



<p>You can now get the best of both worlds. <strong>Koog offers seamless Spring AI integration</strong> and can be easily layered on top as a higher-level agentic runtime.</p>



<h2 class="wp-block-heading">Spring AI</h2>



<p>If you already use <a href="https://spring.io/projects/spring-ai" target="_blank" rel="noreferrer noopener">Spring AI</a>, you&#8217;re familiar with its broad integration landscape: 13+ LLM providers, 18+ vector databases, and 10+ chat memory backends, all built seamlessly into the Spring ecosystem.</p>



<p>Your application likely already relies on some of these integrations and wasn&#8217;t built in isolation. But as your agent’s complexity increases and business requirements demand more reliability, you start needing things that sit above the integration layer, for example, controlled execution logic, guardrails, fault tolerance, and cost optimization. These are the problems <a href="https://www.jetbrains.com/koog/" target="_blank" rel="noreferrer noopener">Koog</a> was built to solve.</p>



<figure class="wp-block-table"><table><tbody><tr><td><strong>Capability</strong></td><td><strong>Spring AI</strong></td><td><strong>Koog</strong></td></tr><tr><td><strong>LLM providers</strong></td><td>✅ 13+</td><td>✅ 16+</td></tr><tr><td><strong>Streaming</strong></td><td>✅ Supported</td><td>✅ Supported</td></tr><tr><td><strong>Tool calling</strong></td><td>✅ Supported</td><td>✅ Supported</td></tr><tr><td><strong>Database integrations</strong></td><td>✅ 10+ (e.g. PostgreSQL and MongoDB)</td><td>Uses the underlying ecosystem with a few integrations provided out of the box (e.g. Postgres)&nbsp;</td></tr><tr><td><strong>Vector databases</strong></td><td>✅ 18+ (e.g. Milvus, Weaviate, and PGvector)</td><td>✅ Uses underlying integrations</td></tr><tr><td><strong>RAG (retrieval-augmented generation)</strong></td><td>✅ Supported via advisors and VectorStore</td><td>✅ Supported and integrated into agent workflows</td></tr><tr><td><strong>Chat memory (short-term)</strong></td><td>✅ Supported</td><td>✅ Supported</td></tr><tr><td><strong>Long-term memory</strong></td><td>✅ Supported via vector DB integrations</td><td>✅ Built-in and pluggable (semantic and structured memory)</td></tr><tr><td><strong>Observability</strong></td><td>✅ Basic observability from the Spring ecosystem (Micrometer, etc.),&nbsp;not tailored for LLM or AI observability tooling</td><td>✅ OpenTelemetry support, built-in tailored support for popular LLM or AI observability tooling (e.g. Langfuse, W&amp;B Weave, and Datadog)</td></tr><tr><td><strong>Parallel execution</strong></td><td>❌ Limited, manual</td><td>✅ Native (coroutines and concurrent node execution)</td></tr><tr><td><strong>Agent strategies</strong></td><td>❌ Basic (prompt chaining and tool calling)</td><td>✅ Advanced type-safe graph workflows (multi-step reasoning, branching, tool orchestration, domain modeling approach), advanced planners (LLM-based and GOAP)</td></tr><tr><td><strong>Persistence</strong></td><td>❌ Not built in, only the message history can be saved</td><td>✅ Built-in advanced persistence for the agent’s logic and state</td></tr><tr><td><strong>History compression</strong></td><td>❌ Not built in</td><td>✅ Native support with out-of-the-box advanced strategies (summarization, pruning, and token optimization)</td></tr></tbody></table></figure>



<p>The good news is you don&#8217;t have to choose one or the other, or dramatically change your existing setup to get there. <strong>Koog’s new Spring AI</strong> integration lets you <strong>keep your current LLM providers and databases exactly as they are</strong>, while writing your agents in Koog with minimal configuration changes. Your integration layer stays intact. <strong>Koog simply adds a powerful orchestration runtime on top of it.</strong></p>



<p>Let&#8217;s take a look at how it works. This post uses a Kotlin and Gradle setup for simplicity, but you can also use the recently released native Java Koog API (and, of course, Maven).</p>



<h2 class="wp-block-heading">Koog’s Spring AI integration</h2>



<p>Let&#8217;s say your Spring project already uses three common Spring AI interfaces: <code>ChatModel</code>, <code>ChatMemoryRepository</code>, and <code>VectorStore</code>. Adding Koog on top is just a three-step process.</p>



<p><strong>Step 1:</strong> Keep your existing Spring AI dependencies.</p>



<p></p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">// LLM
implementation("org.springframework.ai:spring-ai-starter-model-openai")

// Chat memory
implementation("org.springframework.ai:spring-ai-starter-model-chat-memory-repository-jdbc")

// Vector store
implementation("org.springframework.ai:spring-ai-starter-vector-store-pgvector")</pre>



<p><strong>Step 2:</strong> Add the Koog integration dependencies.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">// Koog
implementation("ai.koog:koog-agents-jvm:0.8.0")

// Bridges ChatModel to Koog's LLMClient / PromptExecutor
implementation("ai.koog:koog-spring-ai-starter-model-chat:0.8.0")

// Bridges ChatMemoryRepository to Koog's ChatHistoryProvider
implementation("ai.koog:koog-spring-ai-starter-chat-memory:0.8.0")

// Bridges VectorStore to Koog's KoogVectorStore
implementation("ai.koog:koog-spring-ai-starter-vector-store:0.8.0")</pre>



<p><strong>Step 3:</strong> Use the auto-configured Koog beans. Each Koog starter automatically exposes a Spring bean that wraps your existing Spring AI bean:</p>



<figure class="wp-block-table"><table><tbody><tr><td><strong>Spring AI interface</strong></td><td><strong>Koog bean(s)</strong></td></tr><tr><td><code>ChatModel</code>&nbsp;</td><td><code>PromptExecutor</code>, <code>LLMClient</code></td></tr><tr><td><code>ChatMemoryRepository</code></td><td><code>ChatHistoryProvider</code></td></tr><tr><td><code>VectorStore</code></td><td><code>KoogVectorStore</code></td></tr></tbody></table></figure>



<p>The beans are auto-configured by default when there is a single matching Spring AI candidate, so your existing Spring AI application config stays untouched.</p>



<p>That&#8217;s it for setup. Now let&#8217;s walk through what you can build. To make things concrete, we&#8217;ll use a customer support agent as our running example and progressively add capabilities.</p>



<h2 class="wp-block-heading">When a pure Spring AI agent reaches its limit</h2>



<p>One version of an agent that you could build in pure Spring AI would look like this:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Service
class CustomerSupportService(
    chatClientBuilder: ChatClient.Builder,
    vectorStore: VectorStore,
    chatMemory: ChatMemory,
) {
    
    // Build a fully configured ChatClient once at construction time
    private val chatClient: ChatClient = chatClientBuilder
        .defaultSystem("""
            You are an e-commerce support assistant.
            Be concise and policy-aware.
            Never invent order data.
            If order context is missing for an order-specific request, ask for it.
        """.trimIndent())
        .defaultAdvisors(
            // Vector store RAG advisor – enriches every prompt with relevant docs
            QuestionAnswerAdvisor(
                vectorStore,
                SearchRequest.builder()
                    .topK(4)
                    .similarityThreshold(0.7)
                    .build()
            ),
            // Sliding-window chat memory advisor – keeps last N turns per session
            MessageChatMemoryAdvisor(chatMemory)
        )
        .build()
    
    suspend fun createAndRunAgent(userPrompt: String, sessionId: String): String? =
        chatClient.prompt()
            .user(userPrompt)
            // Scope memory to session
            .advisorParam(ChatMemory.CONVERSATION_ID, sessionId)
            .call()
            .tools()
            .content()
}</pre>



<p>This agent implements a simple tool-calling loop that runs on top of the LLM defined in the config and inserted as a <code>ChatClient</code>. Besides this, the agent has two features. The first is <code>QuestionAnswerAdvisor</code>, which is built on top of <code>VectorStore</code> and behaves like RAG, enriching the conversation with relevant information from external docs. The second is <code>ChatMemory</code>, which keeps only a specified number of messages, helping you control the number of messages in a conversation and save tokens.</p>



<p>But what if we don’t want a window of messages but a message history summary instead? Or, increasing complexity, what if, instead of a primitive tool-calling agentic loop, we wanted a more controllable and tailored strategy with different e-commerce support scenarios, or persistence and durable execution to make our agent fault-tolerant? <strong>This is where we reach the limits of Spring AI.</strong> But these, and many other agentic features, <strong>already exist in Koog and, thanks to the integration, they can easily be built on top of what you&#8217;ve already set up for Spring AI in your project</strong>.&nbsp;</p>



<h2 class="wp-block-heading">What does Koog’s Spring AI integration enable?</h2>



<p>First of all, this is what our e-commerce agent would look like in Koog.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Service
class CustomerSupportService(
    private val promptExecutor: PromptExecutor,
    private val chatStorage: ChatHistoryProvider,
    private val knowledgeBase: SearchStorage&lt;TextDocument, SimilaritySearchRequest>
) {

    suspend fun createAndRunAgent(userPrompt: String): String {
        val agentConfig = AIAgentConfig(
            prompt = prompt("ecommerce-support") {
                system(
                    """
                        You are an e-commerce support assistant.
                        Be concise and policy-aware.
                        Never invent order data.
                        If order context is missing for an order-specific request, ask for it.
                    """.trimIndent()
                )
            },
            model = OpenAIModels.Chat.GPT5Nano,
            maxAgentIterations = 100
        )

        val toolRegistry = ToolRegistry {
            tools(EcommerceSupportTools())
        }

        val agent = AIAgent(
            promptExecutor = promptExecutor,
            agentConfig = agentConfig,
            toolRegistry = toolRegistry,
	    // Simple tool-calling loop strategy
	    strategy = singeRunStrategy()
        ) {

            // Vector store RAG advisor – enriches every prompt with relevant docs
            install(LongTermMemory) {
                retrieval {
                    storage = knowledgeBase
                    searchStrategy = SimilaritySearchStrategy(
                        topK = 4,
                        similarityThreshold = 0.70
                    )
                    promptAugmenter = UserPromptAugmenter()
                }
            }

            // Sliding-window chat memory advisor – keeps last N turns per session
            install(ChatMemory) {
                chatHistoryProvider = chatStorage
                windowSize(20)
            }
        }

        return agent.run(userPrompt)
    }
}</pre>



<p>With Koog&#8217;s Spring AI integration, the <code>PromptExecutor</code> bean is auto-configured from your existing Spring AI <code>ChatModel</code>. You inject it directly into your service – no boilerplate configuration class needed.</p>



<p>The same is true for the doc database and chat memory storage features. You don’t need to make any changes to the application config. With Koog beans, they are seamlessly injected into Koog’s <code>LongTermMemory</code> and <code>ChatMemory</code> and used under the hood.</p>



<h2 class="wp-block-heading">What can you add on top?</h2>



<h3 class="wp-block-heading">Controllable type-safe workflows</h3>



<p>Simple LLM loops lack predictability and control for enterprise scenarios. Each iteration is opaque. You can&#8217;t branch based on tool results, retry failed steps, or enforce specific conversation flows. For production support agents handling refunds, escalations, or multi-step verifications, you need explicit control over the execution path.</p>



<p>With Koog, in addition to using predefined strategies (such as default loop or ReAct), you can customize a strategy using graphs:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val agent = AIAgent(
    promptExecutor = promptExecutor,
    agentConfig = agentConfig,
    toolRegistry = toolRegistry,
    // Graph strategy, can accept and return anything!
    strategy = strategy&lt;String, String>("ecommerce_support") {
        // Define graph here
    }
)</pre>



<p>Instead of putting all of the instructions in a single naive text prompt, the best way to do this is to use structured output and then append an intent-specific prompt to it. This approach reduces the amount of context and gives you more control.&nbsp;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@SerialName("SupportIntent")
@Serializable
enum class SupportIntent {
    ORDER_STATUS,
    CHANGE_ADDRESS,
    REFUND,
    OTHER
}

@Serializable
@LLMDescription("Normalized support request extracted from a user message.")
data class SupportRequest(
    @property:LLMDescription("Detected support intent")
    val intent: SupportIntent,

    @property:LLMDescription("Order ID if present, otherwise null")
    val orderId: String? = null,
)

val graphStrategy = strategy&lt;String, String>("ecommerce_support") {
    // 1) Detect the intent of the request from user message
    val classifyRequest by nodeLLMRequestStructured&lt;SupportRequest>(
        examples = listOf(
            SupportRequest(
                intent = SupportIntent.ORDER_STATUS,
                orderId = "84721",
                userRequest = "Check the status of order 84721"
            )
        )
    )
}</pre>



<p>Once you know the intent, you can append intent-specific instructions or narrow down the required tools and delegate the task to a subgraph with a tool-calling loop:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val graphStrategy = strategy&lt;String, String>("ecommerce_support") {
    ...
    // 2) Check that all request information is provided
    val checkRequest by node&lt;SupportRequest, CheckRequestResult> { request ->
        when {
            request.intent == SupportIntent.OTHER ->
                CheckRequestResult(
                    request = request,
                    needsMoreInfo = true,
                    clarificationQuestion = "Specify the intent: order status, refund, change address?"
                ) 
            ...
            else ->
                CheckRequestResult(
                    request = request,
                    needsMoreInfo = false
                )
        }
    }

    // 3a) Process order status request in separate subgraph with additional prompt (or tools subset)
    val orderStatusFlow by subgraphWithTask&lt;SupportRequest, String>(
        tools = EcommerceSupportTools().asTools()
    ) { req ->
        """
            Handle this request as an ORDER STATUS case.
            Use the order status tool and then answer the user clearly.
            Request: ${req.userRequest}
            Order ID: ${req.orderId}
        """.trimIndent()
    }

    // 3b) Process other intents
    ...
}</pre>



<p>Finally, you can organize each step of your workflow into a graph using type-safe edges and conditions that control your agent&#8217;s behavior:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val graphStrategy = strategy&lt;String, String>("ecommerce_support") {
    ...
    // Chain all nodes by edges
    edge(nodeStart forwardTo classifyRequest)
    edge(classifyRequest forwardTo checkContext 
        onCondition { it.isSuccess } 
        transformed { it.getOrThrow().data }
    )
    edge(classifyRequest forwardTo nodeFinish 
        onCondition { it.isFailure }
        transformed { "Failed to classify request." }
    )
    // If more information is required
    edge(checkContext forwardTo nodeFinish
        onCondition { it.needsMoreInfo }
        transformed { it.clarificationQuestion }
    )
    // If we know the intent
    edge(checkContext forwardTo orderStatusFlow
        // Add intent == SupportIntent.ORDER_STATUS condition for the transition  
        onCondition { request.intent == SupportIntent.ORDER_STATUS }
        transformed { it.request }
    )
    ...
    edge(orderStatusFlow forwardTo nodeFinish)
}</pre>



<p>You have complete freedom to experiment and make the agent as complex as you need it to be.</p>



<figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/04/image-37.png" alt="" class="wp-image-701879"/></figure>



<h3 class="wp-block-heading">Persistence (durable execution)</h3>



<p>There&#8217;s complex logic at play, so you need to be extremely careful not to lose the execution point and state. And thanks to graphs, that&#8217;s possible. Just install and configure the <code>Persistence</code> feature, which will also use the data source from Spring!</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Service
class CustomerSupportService(
    private val dataSource: DataSource,
    ...
) {
    ...
    val agent = AIAgent(
        ...
    ) {
        // Make agent fault-tolerant using Koog's persistence.
        // The agent will recover from the exact graph node where it crashed
        install(Persistence) {
            // Configure where to store the checkpoints:
            storage = PostgresJdbcPersistenceStorageProvider(dataSource)
        }
    }
}</pre>



<p>The persistence feature allows the agent to recover from the exact graph node where it failed and continue execution, which is essential for building reliable services.</p>



<h3 class="wp-block-heading">History compression</h3>



<p>Once you start scaling your AI agents to millions of users and longer-running sessions, managing LLM costs becomes critical. Each step of the agent&#8217;s execution, typically a tool call or an LLM request, adds to the message history, and every token has a price. Beyond cost, every model has a context window limit that&#8217;s easy to hit when processing large documents, handling tool outputs, or running extended sessions.</p>



<p>You don&#8217;t want to silently drop earlier messages when the window fills up. But you also don&#8217;t want to pay for irrelevant tokens or risk the model losing important context. Instead of dropping the history, you can replace it with a summary:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">private fun AIAgentGraphContextBase.tooManyTokensSpent(): Boolean = 
    llm.prompt.latestTokenUsage > 1000

val graphStrategy = strategy&lt;String, String>("ecommerce_support") {
    ...
    // Compress history node with compression strategy
    val compressLLMHistory by nodeLLMCompressHistory&lt;String>(
        // Substitute every 5 messages with TL;DRs
        strategy = HistoryCompressionStrategy.Chunked(5)
    )
    // Do nothing node for navigation only
    val maybeCompressHistory by nodeDoNothing&lt;String>()

    edge (orderStatusFlow forwardTo maybeCompressHistory)
    edge (maybeCompressHistory forwardTo compressLLMHistory 
        onCondition { tooManyTokensSpent() }
    )
    edge (maybeCompressHistory forwardTo nodeFinish 
        onCondition { !tooManyTokensSpent() }
    )
    edge (compressLLMHistory forwardTo nodeFinish)
}</pre>



<p>After adding history compression into the strategy, our updated graph workflow for the&nbsp; e-commerce agent would look like this:</p>



<figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/04/image-36.png" alt="" class="wp-image-701779"/></figure>



<p>Check out the full example in <a href="https://github.com/JetBrains/koog/blob/develop/examples/spring-ai-kotlin/src/main/kotlin/com/example/spring_ai_kotlin/service/customersupport/CustomerSupportGraphService.kt" target="_blank" rel="noreferrer noopener">Kotlin</a> or <a href="https://github.com/JetBrains/koog/blob/develop/examples/spring-ai-java/src/main/java/com/example/spring_ai_java/service/customersupport/CustomerSupportGraphService.java" target="_blank" rel="noreferrer noopener">Java</a>.</p>



<h2 class="wp-block-heading">The bottom line</h2>



<p>In this article, we saw how you can use Koog and Spring AI together to benefit from Spring AI’s model connections and database integrations, as well as the advanced production-focused orchestration layer from the Koog framework.</p>



<p>If you want to learn more about Koog, its <a href="https://www.jetbrains.com/koog/" target="_blank" rel="noreferrer noopener">product page</a> is a good place to start, and if you have any questions or feedback, be sure to join the <a href="https://github.com/JetBrains/koog/discussions" target="_blank" rel="noreferrer noopener">discussion on GitHub</a>.</p>



<p>Finally, don’t forget to join <a href="https://kotlinlang.slack.com/archives/C08SLB97W23" data-type="link" data-id="https://kotlinlang.slack.com/archives/C08SLB97W23" target="_blank" rel="noreferrer noopener">#koog-agentic-framework</a> on the Kotlin Slack<strong>&nbsp;</strong>(get an invite&nbsp;<a href="http://slack.kotlinlang.org/" target="_blank" rel="noreferrer noopener">here</a>).</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>KotlinConf’26 Speakers: In Conversation With Lena Reinhard</title>
		<link>https://blog.jetbrains.com/kotlin/2026/04/kotlinconf-26-speakers-in-conversation-with-lena-reinhard/</link>
		
		<dc:creator><![CDATA[Daria Voronina]]></dc:creator>
		<pubDate>Thu, 02 Apr 2026 06:34:59 +0000</pubDate>
		<featuredImage>https://blog.jetbrains.com/wp-content/uploads/2026/03/Blog-featured-1.png</featuredImage>		<category><![CDATA[news]]></category>
		<category><![CDATA[interview]]></category>
		<category><![CDATA[kotlinconf]]></category>
		<category><![CDATA[lena-reinhard]]></category>
		<guid isPermaLink="false">https://blog.jetbrains.com/?post_type=kotlin&#038;p=694529</guid>

					<description><![CDATA[“Over the last three to five years, many of the promises that drew people to tech have been called into question.” The tech industry has long promised opportunity, growth, and the chance to build things that reach millions of people. Today, many of those assumptions are being questioned. At KotlinConf’26, Lena Reinhard, leadership coach, former [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h3 class="wp-block-heading"> <em>“Over the last three to five years, many of the promises that drew people to tech have been called into question.”</em></h3>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/lena-reinhard.png" alt="KotlinConf'26 speaker: Lena Reinhard" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Lena Reinhard, VP Engineering, leadership coach &#038; mentor, facilitator, artist</h4>
                                                <p><span style="font-weight: 400;">Lena Reinhard is a VP of Engineering, a leadership coach, facilitator, and artist. In her 20-year career, she’s served in tech leadership roles, such as VP of Engineering with CircleCI, Travis CI, and as a SaaS startup co-founder and CEO. Now, she helps leaders and teams succeed in co-located and remote teams in organizations ranging in size from startups and scale-ups to corporations.</span></p>
                    </div>
                            </div>
        </div>
    </div>



<p><strong>The tech industry has long promised opportunity, growth, and the chance to build things that reach millions of people. Today, many of those assumptions are being questioned. At KotlinConf’26, Lena Reinhard, leadership coach, former VP of Engineering, and the Day 2 keynote speaker, will explore these shifts in her talk <em><a href="https://kotlinconf.com/schedule/?day=2026-05-22&amp;session=e0c4884c-4b4b-5ce5-ba3c-5ab47532975d" target="_blank" rel="noopener">We Were Meant to Be</a>.</em></strong></p>



<p><strong>Ahead of the conference, we spoke with Lena about the uncertainty many people in tech are feeling today, the realities behind the productivity debate in the age of AI, and what leaders can do to support their teams through change.</strong></p>



<p><strong>As she prepares for <a href="https://kotlinconf.com/" target="_blank" data-type="link" data-id="https://kotlinconf.com/?utm_source=blogpost&amp;utm_medium=referral&amp;utm_campaign=firstspeakers" rel="noreferrer noopener">KotlinConf ’26</a>, Lena is documenting the process of shaping this keynote in a public work log, sharing the ideas and resources influencing her thinking. You can follow her progress here: <a href="https://www.lenareinhard.com/articles/im-writing-a-keynote-on-the-crisis-the-tech-industry-and-humans-are-in-this-is-my-work-log-everything-im-wrestling-with" target="_blank" rel="noreferrer noopener"><em>The Making of: A Keynote on Tech, Humanity, Crisis, and the Future.</em></a></strong></p>



<div class="buttons">
        <div class="buttons__row">
            <a class="ek-link jb-download-button" title="Meet Lena Reinhard at KotlinConf’26" href="https://kotlinconf.com/schedule/?utm_source=blog&#038;utm_medium=button&#038;utm_campaign=interview-josh-long&#038;day=2026-05-22&#038;session=e0c4884c-4b4b-5ce5-ba3c-5ab47532975d" target="_blank" rel="noopener" data-test="blog-article-cta" data-cl="true">Meet Lena Reinhard at KotlinConf’26</a>
         </div>
</div>



<h3 class="wp-block-heading"><strong>Q: In your keynote </strong><strong><em>We Were Meant to Be</em></strong><strong>, you touch on uncertainty, job insecurity, and how the tech industry is changing. What questions or experiences led you to create this talk, and what do you hope the audience sits with after hearing it?</strong></h3>



<p><strong>Lena Reinhard:</strong> This is probably the question where I have the longest answer, because there’s a lot of history to this. And that’s also why I’m so excited to talk about it at KotlinConf in May.</p>



<p>My career is over 20 years old now. I actually started in finance, and very early on, the industry went through the 2008 financial crisis. So that was a weird way to start a career.</p>



<p>I’ve now been in tech for 16 years, and during that time I’ve seen many shifts in how the industry works. In the early 2010s, I worked a lot in open source. That’s really how I started my tech career, working with communities like CouchDB and some in the JavaScript ecosystem. Later, I shifted more into working with companies in Silicon Valley while still staying close to open source.</p>



<p>Over the last few years, I’ve worked more with leaders across different companies, from startups to large corporations to NGOs all around the world. That means my lens on the industry has changed over time, depending on who I’m working with and which aspects of the ecosystem I’m seeing.So throughout my career, I’ve spent a lot of time thinking about how technology works and what responsibility we have as people building it. In 2015, I gave the keynote <em><a href="https://www.youtube.com/watch?v=D3e3V66TH2Y" target="_blank" data-type="link" data-id="https://www.youtube.com/watch?v=D3e3V66TH2Y" rel="noreferrer noopener">A Talk About Nothing</a></em> that encapsulated a lot of my thoughts at that point in time, and the question of our role as people building software and the responsibilities that come with that.</p>


    <div class="blockquote">
                    <blockquote><p>“<i>The work we do has a lot of leverage, and the question is how we use that in a way that benefits not only us but also the people who use technology.</i>”</p></blockquote>
            <div class="blockquote__author">
                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="blockquote__author-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/lena-reinhard.png" alt="KotlinConf'26 speaker: Lena Reinhard">
                                <div class="blockquote__author-info">
                                                        </div>
            </div>
            </div>



<p>Over the last four or five years, especially since generative AI really took off around 2022, I’ve noticed a lot of uncertainty among industry professionals.</p>



<p>People entered tech for many reasons: building products that reach millions of users, the opportunity for upward mobility, or simply the ability to experiment and create.</p>


    <div class="blockquote">
                    <blockquote><p>“<i>Over the last three to five years, many of those things have been called into question. Software engineers, but also managers, are asking themselves, each other, and sometimes me, how career growth will work, or whether those careers will even exist in the same way. And that uncertainty has only been increasing, and the way that the discourse about this is playing out across the media, from podcasts and social media, to newspapers and “thought leaders,” isn’t helping that.</i>”</p></blockquote>
            <div class="blockquote__author">
                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="blockquote__author-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/lena-reinhard.png" alt="KotlinConf'26 speaker: Lena Reinhard">
                                <div class="blockquote__author-info">
                                                        </div>
            </div>
            </div>



<p>At this point, I think people who claim to have definitive answers about what AI will mean for the global economy or for the tech industry, let alone for individuals and our careers, simply don’t have them. Those answers don’t exist at this point.</p>



<p>There are many hypotheses, and it’s important to stay open to them. But it also means that many of the promises that originally motivated people to enter this field are no longer as stable as they once felt.</p>



<p>Even the way people tinker with technology has changed. I know many programmers who used to build countless side projects in their spare time, and even that culture has shifted.</p>



<p>All of those questions and that uncertainty from the past few years ultimately led to this talk.</p>



<h3 class="wp-block-heading"><strong>Q: You’ve written a lot about how to understand and improve productivity in engineering teams. (For example, your article </strong><a href="https://www.lenareinhard.com/articles/software-engineering-understand-measure-improve-productivity-doing-the-right-thing-better-how-to-lead-teams-with-efficiency-effectiveness" target="_blank" rel="noreferrer noopener"><strong><em>How to Understand, Measure, and Improve Productivity in Your Engineering Team</em></strong></a><strong><em>.</em>) With AI becoming more present in our daily work, how do you think our ideas of productivity are shifting, or need to shift, for individuals and teams?</strong></h3>



<p><strong>Lena:</strong> It&#8217;s a great question. And I think the two are very intertwined.</p>


    <div class="blockquote">
                    <blockquote><p>“<i>One thing I often think about is that engineering productivity, and the discourse around it, has been a hot mess for a very long time.</i>”</p></blockquote>
            <div class="blockquote__author">
                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="blockquote__author-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/lena-reinhard.png" alt="KotlinConf'26 speaker: Lena Reinhard">
                                <div class="blockquote__author-info">
                                                        </div>
            </div>
            </div>



<p>It’s always been a mix of the work people are doing, how meaningful that work is, and how productive that work appears from the outside.</p>



<p>For example, does your executive team think that you&#8217;re actually getting stuff done? And those can be very different things that don’t necessarily overlap.</p>



<p>So productivity has always been difficult for teams. I also don’t know of a company that has really figured it out well. It’s always somewhat ambiguous.</p>



<p>Now, with generative AI and coding assistants entering the picture, the conversation has become even more complicated.</p>


    <div class="blockquote">
                    <blockquote><p>“<i>One big issue is that a lot of the current AI discussion is surrounded by hype and marketing messages that aren’t really backed up by solid data or real-world experience.</i>”</p></blockquote>
            <div class="blockquote__author">
                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="blockquote__author-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/lena-reinhard.png" alt="KotlinConf'26 speaker: Lena Reinhard">
                                <div class="blockquote__author-info">
                                                        </div>
            </div>
            </div>



<p>At the same time, executives and senior leaders are often driven by pressure from their boards and investors. At this point, many leaders feel they can’t say, “We’re not doing AI,” because their investors will worry the company is falling behind.</p>



<p>So there are a lot of really messy incentives around this that engineering teams get caught up in.</p>



<p>Navigating that debate is difficult right now. It requires open conversations internally – with managers and teammates.My approach right now is that it’s important to talk about what productivity actually means and how it relates to the company’s goals. I recently wrote more about this in my article <a href="https://www.lenareinhard.com/articles/what-ai-can-cant-do-for-your-engineering-team-beyond-the-hype-engineer-roles" target="_blank" rel="noreferrer noopener"><em>What AI Can (and Can&#8217;t) Do for Your Engineering Team (Beyond the Hype)</em></a>, where I look at some of the current limitations of AI and where it can actually be useful for teams.</p>


    <div class="blockquote">
                    <blockquote><p>“<i>The goal can’t simply be to get as much stuff done and move as fast as possible. If what you&#8217;re working on doesn’t actually help the company achieve its goals, then being fast doesn’t get you anywhere.</i>”</p></blockquote>
            <div class="blockquote__author">
                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="blockquote__author-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/lena-reinhard.png" alt="KotlinConf'26 speaker: Lena Reinhard">
                                <div class="blockquote__author-info">
                                                        </div>
            </div>
            </div>



<p>So the conversation should start with: what are our goals, how do we measure progress toward them, and how can AI actually help us get there?</p>



<p>For some teams, AI can be useful for experimentation. For others, it can help with debugging or act as a coding assistant in everyday workflows.</p>



<p>But the key is cutting through the hype and figuring out what is actually useful for your team and for the problems you’re solving for your users.</p>



<p>One thing that concerns me is that AI is already increasing the pressure on teams to produce more output.</p>



<p>I’m seeing discussions again where people think lines of code generated by AI are a useful productivity metric, which they are not. That’s a debate I thought we had already moved past about ten years ago.</p>



<p>At the same time, what I’m hearing from many teams is that people are simply working much more. Instead of working less, they’re working more hours because now, in addition to their regular job, they’re also expected to figure out how to integrate AI into their work, and the scrutiny on “productivity”, most commonly meaning “output”, not outcomes, is intense.</p>



<p>So my advice right now is to cut through the noise as much as possible. Don’t fall for the hype around just running as fast as possible. Focus on the goals: what your team is responsible for, how that connects to the company’s goals, and what meaningful progress and impact actually look like.</p>



<p>I talk about goals until the cows come home, because that’s what teams should ultimately be measured against.</p>



<p>Moving fast only matters if you’re moving in the right direction.</p>


    <div class="blockquote">
                    <blockquote><p>“<i>One way I often describe generative AI tools is that they’re like an overly eager junior engineer who’s extremely confident.</i>”</p></blockquote>
            <div class="blockquote__author">
                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="blockquote__author-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/lena-reinhard.png" alt="KotlinConf'26 speaker: Lena Reinhard">
                                <div class="blockquote__author-info">
                                                        </div>
            </div>
            </div>



<p>That kind of person can be great to work with, but they also require constant monitoring and guidance. It’s going to tell you stuff that’s just not true, not out of malice, of course, it doesn’t have a world model, and it’s important that we don’t anthropomorphize these tools. And it’s going to say it in a way that makes you think, “Oh yeah, that sounds great,” but actually it’s just nonsense. And that creates a lot of overhead and context switching. The mental load for teams right now is just much higher than it used to be.</p>



<p>That doesn’t mean the tools are useless. But they require a lot of handholding to produce useful results. They’re currently most useful for people with significant experience as software engineers who know what good software engineering looks like, how it works, and who can then utilize these tools well and productively. Where it gets tricky is that both the process of generation as well as the output <em>look </em>very good and convincing to the untrained eye. That’s where unhelpful discussions come in, like CEOs saying, “I vibe-coded this in two hours, why does our engineering team need this many people, and why are they producing so little? Also, I put my thing live just now.” That’s a tough position to be in.</p>



<div class="buttons">
        <div class="buttons__row">
            <a class="ek-link jb-download-button" title="Join us at KotlinConf’26" href="https://pretix.eu/jetbrains/kotlinconf2026/c/x97gJcrj3/?utm_source=blog&#038;utm_medium=button&#038;utm_campaign=interview-lena-reinhard" target="_blank" rel="noopener" data-test="blog-article-cta" data-cl="true">Join us at KotlinConf’26</a>
         </div>
</div>



<h3 class="wp-block-heading"><strong>Q: In your talk description, you say that many of the promises of tech careers have crumbled. From what you’re seeing and hearing, what still draws people to tech today – and how do you think that motivation might evolve?</strong></h3>



<p><strong>Lena:</strong> Honestly, right now I find that question difficult to answer.</p>



<p>When I look at the people I talk to, and also at discussions in online forums for people who are just entering the field or participating in different communities, my impression is that many people are still drawn by the promises the industry used to offer – things like career progression and stable jobs; the same for building things, being creative, and solving problems.</p>



<p>Those ideas haven’t completely disappeared.</p>



<p>But at the same time, people are much more uncertain about how true those promises still are and how much they can and want to bet their ability to make a decent living on them. There’s a lot more doubt about whether those careers will still exist in the same way, or whether people should pursue something else.</p>



<p>So that uncertainty that’s affecting the entire industry is visible there as well.</p>



<p>And the noise-to-signal ratio is incredibly high. Like we briefly touched on earlier, the debate on social media, industry newsletters, at conferences, etc., also exists about “whether software engineering jobs will still exist in the future.” Those debates don’t really help, and again, no one has the answers.</p>



<h3 class="wp-block-heading"><strong>Q: You work closely with leaders and speak a lot about leadership. For example, you explored the topic in your </strong><a href="https://youtu.be/QQRVKzQP_JA?si=9IUXeLCTDDyWz4xi" target="_blank" rel="noreferrer noopener"><strong>LeadDev talk</strong></a><strong> on what we really mean when we talk about leadership. In periods of change and instability like the ones many teams are facing now, what do you think leaders most often underestimate about how uncertainty affects their teams?</strong></h3>



<p><strong><em>Lena:</em></strong> One big piece is that leaders often have an information advantage.</p>



<p>Managers – and often technical leads and very senior engineers – are often briefed about changes long before their teams are. They are involved in discussions about reorganizations before they happen, or in creating a new technical strategy.</p>



<p>So they’re often part of shaping those changes, or at least they know about them well in advance.</p>


    <div class="blockquote">
                    <blockquote><p>“<i>When leaders announce a change to their team, they’ve often already processed it. Mentally, they’ve moved on. But for the team, it’s completely new information.</i>”</p></blockquote>
            <div class="blockquote__author">
                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="blockquote__author-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/lena-reinhard.png" alt="KotlinConf'26 speaker: Lena Reinhard">
                                <div class="blockquote__author-info">
                                                        </div>
            </div>
            </div>



<p>People need time to process it. They need time to understand what it actually means for them – how it will affect their day-to-day work, their role, how they get things done, or even what success will look like going forward.</p>



<p>I’ve often worked with leaders who become impatient at that stage. They wonder why people can’t just get on board immediately, or why there are so many questions.</p>



<p>But it’s important to remember that you may be in a very different place simply because you’ve had that information for much longer.</p>



<p>Giving people time and actually sitting down with them, explaining things, and listening to their questions requires effort, but it’s really important. Esther Derby, who started as a programmer and has written great books about agile work and handling change, likes to describe what leaders then tend to call “resistance” to change rather than a “response.” <a href="https://www.lenareinhard.com/articles/understanding-overcoming-resistance-to-change-in-your-organisation" target="_blank" rel="noreferrer noopener">I wrote about dealing with these kinds of responses here</a>.</p>



<p>Another pattern I see is that some leaders feel they need to have everything completely figured out before they talk to their teams.</p>



<p>But especially right now, there’s so much uncertainty inside companies and across the entire industry that none of us can really control it.</p>



<p>Things are changing quickly: companies are redesigning career frameworks, rethinking productivity measures, and trying to figure out what the future of work even looks like.</p>



<p>As a leader, you don’t always need to have everything figured out.</p>



<p>Sometimes it’s more helpful to simply acknowledge the uncertainty to say openly that things are chaotic or unclear right now.</p>



<p>That helps address the elephant in the room. It prevents people from feeling like something strange is happening behind the scenes, and it makes it easier to have open conversations.</p>



<p>Because the reality is that no one really has all the answers.</p>


    <div class="blockquote">
                    <blockquote><p>“<i>Leaders often assume that their teams expect certainty from them. But in many cases, what people actually need is openness.</i>”</p></blockquote>
            <div class="blockquote__author">
                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="blockquote__author-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/lena-reinhard.png" alt="KotlinConf'26 speaker: Lena Reinhard">
                                <div class="blockquote__author-info">
                                                        </div>
            </div>
            </div>



<p>Being able to say, “I don’t have all the answers, but I’m working through this with you,” is often much more useful.</p>



<p>And empathy matters as well.</p>



<p>Instead of projecting what you think people need, it’s important to sit down with them and understand what they actually need.</p>



<p>Because those two things can be very different.</p>



<p><strong>Lena will explore these ideas in more depth in her keynote at KotlinConf’26.</strong></p>



<p><strong>Don’t miss <a href="https://kotlinconf.com/schedule/?day=2026-05-22&amp;session=e0c4884c-4b4b-5ce5-ba3c-5ab47532975d" target="_blank" data-type="link" data-id="https://kotlinconf.com/schedule/?day=2026-05-22&amp;session=e0c4884c-4b4b-5ce5-ba3c-5ab47532975d" rel="noreferrer noopener">Lena’s Day 2 keynote</a>.</strong></p>



<div class="buttons">
        <div class="buttons__row">
            <a class="ek-link jb-download-button" title="Join us at KotlinConf’26" href="https://pretix.eu/jetbrains/kotlinconf2026/c/x97gJcrj3/?utm_source=blog&#038;utm_medium=button&#038;utm_campaign=interview-lena-reinhard" target="_blank" rel="noopener" data-test="blog-article-cta" data-cl="true">Join us at KotlinConf’26</a>
         </div>
</div>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Kodee&#8217;s Kotlin Roundup: Kotlin 2.3.20, Interview With Josh Long, and More</title>
		<link>https://blog.jetbrains.com/kotlin/2026/03/kodees-kotlin-roundup-march-26-edition/</link>
		
		<dc:creator><![CDATA[Kodee]]></dc:creator>
		<pubDate>Tue, 31 Mar 2026 09:27:05 +0000</pubDate>
		<featuredImage>https://blog.jetbrains.com/wp-content/uploads/2026/03/KT-social-BlogFeatured-1280x720-1-5.png</featuredImage>		<category><![CDATA[news]]></category>
		<category><![CDATA[kotlin-roundup]]></category>
		<guid isPermaLink="false">https://blog.jetbrains.com/?post_type=kotlin&#038;p=692923</guid>

					<description><![CDATA[March was a busy month for Kotlin, with a new language release, fresh tooling, ecosystem updates, and plenty of inspiration ahead of KotlinConf&#8217;26. From practical improvements to exciting steps in AI and multiplatform, there&#8217;s a lot worth exploring. Here are the stories that stood out to me most. Where you can learn more YouTube highlights]]></description>
										<content:encoded><![CDATA[
<p>March was a busy month for Kotlin, with a new language release, fresh tooling, ecosystem updates, and plenty of inspiration ahead of KotlinConf&#8217;26. From practical improvements to exciting steps in AI and multiplatform, there&#8217;s a lot worth exploring. Here are the stories that stood out to me most.</p>


            <div class="newsletter">
                            <h2>Kodee-Approved Spotlight</h2>
                                                            <article class="newsletter__post">
                                                                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="newsletter__post-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/kotlin-2-3-20-blog-post.png" alt="">
                                                                            <div class="newsletter__post-text">
                                                            <h3>Kotlin 2.3.20 is out</h3>
                                                        <p>A fresh Kotlin release always catches my attention, especially when it focuses on improving everyday development. Kotlin <strong>2.3.20</strong> brings bug fixes, performance improvements, and small but meaningful enhancements across the ecosystem. It’s the kind of update that strengthens the foundation and makes your day-to-day work more stable.</p>
                                                            <a href="https://blog.jetbrains.com/kotlin/2026/03/kotlin-2-3-20-released/" class="btn" target="_blank">See what’s new</a>
                                                    </div>
                    </article>
                                    <article class="newsletter__post">
                                                                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="newsletter__post-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/social.png" alt="">
                                                                            <div class="newsletter__post-text">
                                                            <h3>Kotlin Foundation Grants Program winners announced</h3>
                                                        <p>Out of 117 applications, only five could walk away with a grant – and what a five. <a href="https://github.com/GitLiveApp/firebase-kotlin-sdk" target="_blank" rel="noopener">Firebase Kotlin SDK</a>, <a href="https://github.com/GradleUp/shadow" target="_blank" rel="noopener">Shadow Gradle Plugin</a>, <a href="https://github.com/lupuuss/Mokkery" target="_blank" rel="noopener">Mokkery</a>, <a href="https://github.com/Anamorphosee/stacktrace-decoroutinator" target="_blank" rel="noopener">Stack Trace Decoroutinator</a>, and <a href="https://github.com/varabyte/kobweb" target="_blank" rel="noopener">Kobweb</a> were selected to receive a USD 6,000 grant and recognized for their impact, technical quality, and real value to developers. I love seeing this kind of direct investment going to the tools that keep the whole ecosystem growing.</p>
                                                            <a href="https://kotlinfoundation.org/news/grants-program-winners-25/" class="btn" target="_blank" rel="noopener">Meet the winners</a>
                                                    </div>
                    </article>
                                    <article class="newsletter__post">
                                                                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="newsletter__post-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/Blog-Featured.png" alt="KotlinConf’26 Speakers: In Conversation with Josh Long">
                                                                            <div class="newsletter__post-text">
                                                            <h3>KotlinConf’26 speakers: In Conversation with Josh Long</h3>
                                                        <p>I loved this interview with Josh Long, Spring&#8217;s first developer advocate. He shares why <strong>Kotlin feels like a natural fit for Spring</strong> and how the JVM continues to be a strong platform for modern applications, including AI. It’s a great read if you&#8217;re working on backend systems or using Spring.</p>
                                                            <a href="https://blog.jetbrains.com/kotlin/2026/03/kotlinconf-26-speakers-in-conversation-with-josh-long/" class="btn" target="_blank">Read the interview</a>
                                                    </div>
                    </article>
                                    <article class="newsletter__post">
                                                                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="newsletter__post-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/JB-social-BlogFeatured-1280x720-1-6.png" alt="KotlinConf 2026: Talks to Help You Navigate the Schedule">
                                                                            <div class="newsletter__post-text">
                                                            <h3>KotlinConf’26: Talks to help you navigate the schedule</h3>
                                                        <p>KotlinConf&#8217;26 is almost here, and the full schedule is already live. With so many sessions across multiplatform, backend, AI, and language design, choosing what to attend can be a challenge. Take a look and start planning your agenda. Whether you&#8217;re building Kotlin Multiplatform (KMP) apps, scaling backend systems, or exploring AI in Kotlin, these sessions highlight where the ecosystem is heading and what you can apply in your own projects.</p>
                                                            <a href="https://blog.jetbrains.com/kotlin/2026/03/kotlinconf-2026-talks-schedule/" class="btn" target="_blank">Plan your schedule</a>
                                                    </div>
                    </article>
                                    <article class="newsletter__post">
                                                                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="newsletter__post-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/maxresdefault.jpg" alt="Android Gradle Plugin 9.0: What Kotlin developers need to know">
                                                                            <div class="newsletter__post-text">
                                                            <h3>Android Gradle Plugin 9.0: What Kotlin developers need to know</h3>
                                                        <p>Big changes are coming with the latest version of the Android Gradle plugin. In this video, Zac walks through what&#8217;s changing, why it matters, and how to upgrade your Kotlin projects with confidence.</p>
                                                            <a href="https://youtu.be/m0Cq6J-V_RY?si=7Bf-9ejCtVa30Z_A" class="btn" target="_blank" rel="noopener">Watch the video</a>
                                                    </div>
                    </article>
                                    <article class="newsletter__post">
                                                                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="newsletter__post-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/KM-social-BlogFeatured-1280x720-1.png" alt="Experimental Swift Package Manager support for KMP">
                                                                            <div class="newsletter__post-text">
                                                            <h3>Experimental Swift Package Manager support for KMP</h3>
                                                        <p>Here’s something I&#8217;m excited about this month – Swift Package Manager support has landed in Kotlin Multiplatform as an experimental feature. You can now <strong>import iOS dependencies directly from Swift packages</strong> or migrate existing CocoaPods integrations. There&#8217;s even an AI-assisted skill to help with the conversion!</p>
                                                            <a href="https://kotl.in/kmp-swiftpm-import" class="btn" target="_blank" rel="noopener">Try it out</a>
                                                    </div>
                    </article>
                                    <article class="newsletter__post">
                                                                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="newsletter__post-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/IJ-social-BlogFeatured-1280x720-1-2.png" alt="">
                                                                            <div class="newsletter__post-text">
                                                            <h3>IntelliJ IDEA’s new Kotlin coroutine inspections, explained</h3>
                                                        <p>If you’re working with coroutines, this is a must-read. IntelliJ IDEA now features new inspections designed to catch common pitfalls and guide you toward safer, more reliable coroutine usage. It’s a subtle enhancement that can make a significant impact on your daily development.</p>
                                                            <a href="https://blog.jetbrains.com/idea/2026/03/intellij-idea-s-new-kotlin-coroutine-inspections-explained/" class="btn" target="_blank">Explore the details</a>
                                                    </div>
                    </article>
                                    <article class="newsletter__post">
                                                                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="newsletter__post-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/KT-social-BlogFeatured-1280x720-1-1.png" alt="Tracy: The AI Observability Library for Kotlin">
                                                                            <div class="newsletter__post-text">
                                                            <h3>Introducing Tracy: The AI observability library for Kotlin</h3>
                                                        <p>Kotlin keeps growing in the AI space, and it’s just the beginning. Tracy is a new open-source observability library that helps you understand what&#8217;s happening inside AI-powered applications by tracking model calls, tool usage, execution time, and overall flow. No more guessing what your AI is up to.</p>
                                                            <a href="https://blog.jetbrains.com/kotlin/2026/03/introducing-tracy-the-ai-observability-library-for-kotlin/" class="btn" target="_blank">Explore Tracy</a>
                                                    </div>
                    </article>
                                    <article class="newsletter__post">
                                                                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="newsletter__post-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/02/KT-social-BlogFeatured-1280x720-1-4.png" alt="">
                                                                            <div class="newsletter__post-text">
                                                            <h3>Java to Kotlin conversion comes to Visual Studio Code</h3>
                                                        <p>Kotlin is becoming more accessible outside of IntelliJ IDEA, too. We&#8217;ve released the <strong>J2K Converter</strong> extension, bringing Java-to-Kotlin conversion directly to VS Code. Just right-click any Java file and convert it in seconds. It’s powered by the same proven engine as our IntelliJ-based IDEs. I&#8217;ve already tried it – have you?</p>
                                                            <a href="https://marketplace.visualstudio.com/items?itemName=JetBrains.j2k-vscode" class="btn" target="_blank" rel="noopener">Download the extension</a>
                                                    </div>
                    </article>
                                    <article class="newsletter__post">
                                                                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="newsletter__post-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/02/KT-social-BlogFeatured-1280x720-1-1.png" alt="">
                                                                            <div class="newsletter__post-text">
                                                            <h3>Building modular monoliths with Kotlin and Spring</h3>
                                                        <p>When thinking about architecture, I often like approaches that balance simplicity and scalability. Modular monolith architecture allows you to split the application into isolated modules with their own business logic, while still being deployed as a single artifact. It’s a read!</p>
                                                            <a href="https://blog.jetbrains.com/kotlin/2026/02/building-modular-monoliths-with-kotlin-and-spring/" class="btn" target="_blank">Read the article</a>
                                                    </div>
                    </article>
                                    <article class="newsletter__post">
                                                                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="newsletter__post-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/KT-social-BlogSocialShare-1280x720-1-5.png" alt="KotlinConf is just around the corner, and we’re recording short interviews with Kotlin developers who use Junie regularly.">
                                                                            <div class="newsletter__post-text">
                                                            <h3>Love using Junie and Kotlin in your workflow?</h3>
                                                        <p>The camera&#8217;s on, and I&#8217;m ready! We&#8217;re recording short interviews with Kotlin developers who use Junie in their day-to-day workflows. Selected clips will be featured in a compilation video shown at KotlinConf. Want to share your experience and be part of it? Fill out the short form below.</p>
                                                            <a href="https://surveys.jetbrains.com/s3/KotlinConf-Video-Sign-Up-Form" class="btn" target="_blank" rel="noopener">Sign up here</a>
                                                    </div>
                    </article>
                                    </div>
    


<h2 class="wp-block-heading">Where you can learn more</h2>



<ul>
<li><a href="https://kotlinconf.com/workshops/" target="_blank" rel="noopener">Workshops – KotlinConf 2026, May 20–22, Munich</a></li>



<li><a href="https://kotlinlang.org/lp/kotlin-spring-ai-tutorial/" target="_blank" rel="noopener">Spring AI Kotlin Tutorials – Build AI-Powered Applications</a></li>



<li><a href="https://blog.jetbrains.com/kotlin/2026/03/gsoc-2026-contribute-to-kotlin/">Google Summer of Code 2026 Is Here: Contribute to Kotlin</a></li>



<li><a href="https://android-developers.googleblog.com/2026/03/elevating-ai-assisted-androi.html" target="_blank" rel="noopener">Elevating AI-Assisted Android Development and Improving LLMs With Android Bench</a></li>
</ul>



<h2 class="wp-block-heading">YouTube highlights</h2>



<ul>
<li><a href="https://youtu.be/PU-VdH8HhVA?si=mH1Aec213Df8IUPr" target="_blank" rel="noopener">Explicit Backing Fields are experimental in Kotlin 2.3</a></li>



<li><a href="https://www.youtube.com/watch?v=WcQ-bOItdOE" target="_blank" rel="noopener">Kotlin Devs Diversify: Android Is 25% Now</a></li>



<li><a href="https://www.youtube.com/watch?v=Wze7qsDl4BM" target="_blank" rel="noopener">How Major Metros Run on Kotlin Multiplatform | Talking Kotlin #145</a></li>
</ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Amper 0.10 – JDK Provisioning, a Maven Converter, Custom Compiler Plugins, and More</title>
		<link>https://blog.jetbrains.com/amper/2026/03/amper-0-10/</link>
		
		<dc:creator><![CDATA[Kirill Likhodedov]]></dc:creator>
		<pubDate>Tue, 31 Mar 2026 08:20:01 +0000</pubDate>
		<featuredImage>https://blog.jetbrains.com/wp-content/uploads/2026/03/AMP-social-BlogFeatured-1280x720-1.png</featuredImage>		<product ><![CDATA[kotlin]]></product>
		<guid isPermaLink="false">https://blog.jetbrains.com/?post_type=amper&#038;p=695013</guid>

					<description><![CDATA[Amper 0.10.0 is out, and it brings a variety of new features, such as JDK provisioning, custom Kotlin compiler plugins, a Maven-to-Amper converter, and numerous IDE improvements! Read on for all of the details, and see the release notes for the full list of changes and bug fixes. To get support for Amper’s latest features, [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p><a href="https://github.com/JetBrains/amper/releases/tag/v0.10.0" target="_blank" rel="noopener">Amper 0.10.0</a> is out, and it brings a variety of new features, such as JDK provisioning, custom Kotlin compiler plugins, a Maven-to-Amper converter, and numerous IDE improvements! Read on for all of the details, and see <a href="https://github.com/JetBrains/amper/releases/tag/v0.10.0" target="_blank" rel="noopener">the release notes</a> for the full list of changes and bug fixes.</p>



<p><em>To get support for Amper’s latest features, use </em><a href="https://www.jetbrains.com/idea/download/other/#releases-2025" target="_blank" rel="noopener"><em>IntelliJ IDEA 2025.3.4 </em></a><em>&nbsp;or</em><a href="https://www.jetbrains.com/idea/" target="_blank" rel="noopener"><em> IntelliJ IDEA 2026.1</em></a><em> (or newer). Make sure the latest version of the Amper plugin is installed.&nbsp;</em></p>



<h2 class="wp-block-heading">JDK provisioning</h2>



<p>Amper needs a JDK (Java Development Kit) in order to perform various tasks in the project: compile Kotlin and Java sources, run tests, run JVM apps, etc.</p>



<p>Our philosophy is that you should be able to run your project without manually installing anything on your machine or having to configure anything. This is why Amper is able to provision a JDK automatically for you – JDK 21 by default.&nbsp;</p>



<p>However, some projects require specific JDK versions. You can now specify the criteria for the necessary JDK in <code>module.yaml</code>, and Amper will download and install the matching JDK.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="yaml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">settings:
  jvm:
    jdk:
      version: 21 # major version
      distributions: [ zulu, temurin ] # acceptable distributions</pre>



<p>Amper also takes the <code>JAVA_HOME</code> environment variable into account, since it is a common way to set the JDK to be used on the machine. You can read more about Amper’s JDK provisioning behavior <a href="https://amper.org/0.10/user-guide/advanced/jdk-provisioning/#jdk-provisioning" target="_blank" rel="noopener">in the documentation</a>.</p>



<h2 class="wp-block-heading">Maven converter and Maven plugin compatibility</h2>



<p>If you have an existing Maven project, you don’t have to rewrite your build configuration from scratch. This release introduces a semi-automated conversion tool that reads your <code>pom.xml</code> files, including those in multi-module reactor projects, and generates the corresponding <code>project.yaml</code> and <code>module.yaml</code> files for you. To use it, simply run:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="shell" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">./amper tool convert-project</pre>



<p>The converter maps your dependencies, BOMs, repositories, publishing coordinates, compiler flags, and other settings to their Amper equivalents. To support using both build systems during the transition, it sets <code>layout: maven-like</code> in every module so that your source directory structure, including <code>src/main/java</code> and <code>src/main/kotlin</code>, stays the same and no files need to be moved.</p>



<p>Well-known Maven plugins such as <code>maven-compiler-plugin</code> and <code>spring-boot-maven-plugin</code> are translated into built-in Amper settings. Other Maven plugins are added to the new <code>mavenPlugins</code> configuration section in <code>module.yaml</code>, and Amper can execute them during the build process through our <a href="https://amper.org/0.10/user-guide/advanced/maven-plugins/" target="_blank" rel="noopener">Maven plugin compatibility layer</a>.</p>



<p>The conversion is best-effort, so some projects may require tweaks afterward. For a full walkthrough and a list of limitations, see <a href="https://amper.org/0.10/getting-started/migrating-from-maven/" target="_blank" rel="noopener">the documentation</a>.</p>



<h2 class="wp-block-heading">Kotlin compiler plugins</h2>



<p>This release brings support for <a href="https://amper.org/0.10/user-guide/advanced/kotlin-compiler-plugins/#third-party-compiler-plugins" target="_blank" rel="noopener">third-party Kotlin compiler plugins</a>. Enabling this support is as easy as adding the following to <code>module.yaml</code>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="yaml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">settings:
  kotlin:
    compilerPlugins:
      - id: org.example.my.plugin
        dependency: org.example:my-plugin:1.0.0
        options:
          myKey1: myValue1
          myKey2: myValue2</pre>



<p>See <a href="https://amper.org/0.10/user-guide/advanced/kotlin-compiler-plugins/#third-party-compiler-plugins" target="_blank" rel="noopener">the documentation</a> for examples and how to enable IDE support for custom plugins.</p>



<p>We also added built-in support for the <a href="https://amper.org/0.10/user-guide/builtin-tech/kotlinx-rpc/" target="_blank" rel="noopener">kotlinx.rpc</a> and <a href="https://amper.org/0.10/user-guide/advanced/kotlin-compiler-plugins/#js-plain-objects" target="_blank" rel="noopener">JsPlainObjects</a> compiler plugins.&nbsp;</p>



<h2 class="wp-block-heading">IDE improvements</h2>



<h3 class="wp-block-heading">Reworked UX for running Amper commands</h3>



<p>We’ve revisited the UI for creating and editing run configurations in the IDE. New custom views allow you to configure the options for <code>run</code> and <code>test</code> commands in a more convenient way:</p>



<figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/image-55.png" alt="" class="wp-image-695104"/></figure>



<figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/test.png" alt="" class="wp-image-695325"/></figure>



<p>Additionally, you can now create a configuration for any Amper command by choosing <em>Amper</em> in the <em>Add New Configuration</em> menu:</p>



<figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/build.png" alt="" class="wp-image-695336"/></figure>



<p>If you want to run a command in an ad-hoc way, you can use <a href="https://www.jetbrains.com/help/idea/running-anything.html" target="_blank" rel="noopener"><em>Run Anything</em></a> (<em>Ctrl+Ctrl</em>) and prepend your command with amper:</p>



<figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/runanything.png" alt="" class="wp-image-695347"/></figure>



<h3 class="wp-block-heading">Run gutters for native applications in module.yaml</h3>



<p>Native applications (<code>linux/app</code>, <code>macos/app</code>, <code>windows/app</code>) can now be run from the IDE via the gutter:</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/image-57.png" alt="" class="wp-image-695143" style="aspect-ratio:1.38135593220339;width:430px;height:auto; width:100% !important; height:auto !important; max-width:100% !important;"/></figure>



<h3 class="wp-block-heading">Better test names in the <em>Test </em>tool window</h3>



<p>The <code>@DisplayName</code> and <code>@ParameterizedTest.name</code> JUnit 5 annotations are now respected in the <em>Test </em>tool window when showing the test execution tree.<br></p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@ParameterizedTest(name = "Test #{0}")
@DisplayName("My parameterized test")
@ValueSource(ints = [1, 2, 3])
fun parameterized(i: Int) {}</pre>



<figure class="wp-block-image size-full is-resized"><img decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/testwindow.png" alt="" class="wp-image-695358" style="aspect-ratio:1.9409448818897639;width:510px;height:auto; width:100% !important; height:auto !important; max-width:100% !important;"/></figure>



<h3 class="wp-block-heading">Ktor plugin assistance</h3>



<p>If your module has the Ktor server dependency, the <code>module.yaml</code> file provides support for searching and adding plugins via the <em>Add Plugins…</em> inlay:</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/image-60.png" alt="" class="wp-image-695244" style="aspect-ratio:1.4916943521594683;width:387px;height:auto; width:100% !important; height:auto !important; max-width:100% !important;"/></figure>



<p>Alternatively, you can use <a href="https://www.jetbrains.com/help/idea/ktor.html#generate" target="_blank" rel="noopener">completion in the Kotlin code</a>, which will add all the necessary dependencies to the module without you even having to touch the <code>module.yaml</code> file:</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/image-58.png" alt="" class="wp-image-695202" style="aspect-ratio:1.140926640926641;width:537px;height:auto; width:100% !important; height:auto !important; max-width:100% !important;"/></figure>



<h3 class="wp-block-heading">Support for profiling JVM applications</h3>



<p><em>Note: This feature requires IntelliJ IDEA Ultimate.</em></p>



<p>The configuration for the run command in jvm/app modules can now be run using <a href="https://www.jetbrains.com/help/idea/profiler-intro.html" target="_blank" rel="noopener">IntelliJ IDEA’s support for profilers</a>:</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/image-59.png" alt="" class="wp-image-695216" style="aspect-ratio:2.635294117647059;width:435px;height:auto; width:100% !important; height:auto !important; max-width:100% !important;"/></figure>



<h2 class="wp-block-heading">Amper plugin development</h2>



<p><a href="https://blog.jetbrains.com/amper/2025/11/amper-update-november-2025/">The previous release of Amper</a> brought the preview of Amper’s extensibility system. We received a lot of feedback, and we are working on extending the capabilities of plugins. While the ability to publish and share plugins is still a work in progress, a valuable improvement is already available in this release: you can now reference the module settings from the plugin using <code>${module.settings}</code> in <code>plugin.yaml</code>:</p>



<figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/image-56.png" alt="" class="wp-image-695125"/></figure>



<h2 class="wp-block-heading">Other improvements</h2>



<p>Starting with version 0.10, Amper supports<a href="https://maven.apache.org/guides/introduction/introduction-to-profiles.html#Profiles_in_POMs" target="_blank" rel="noopener"> Maven profiles</a> declared in the POM files of transitive dependencies.</p>



<p>In this release, we’ve also introduced the ability to add module descriptions in <code>module.yaml</code>. The description is formatted in Markdown and can occupy multiple lines. This text is used by the <code>./amper show modules</code> command in the CLI, as well as by the IDE to show information about the module. For libraries, it is also used as a description in published metadata by default.</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/showmodules.png" alt="" class="wp-image-695369" style="aspect-ratio:2.8097826086956523;width:517px;height:auto; width:100% !important; height:auto !important; max-width:100% !important;"/></figure>



<h2 class="wp-block-heading">Updated default versions</h2>



<p>We updated some of our default versions for toolchains and frameworks:</p>



<ul>
<li>Kotlin: 2.3.20</li>



<li>Android minimum SDK: 23</li>



<li>Compose: 1.10.3</li>



<li>KSP: 2.3.6</li>



<li>Ktor: 3.4.1</li>



<li>Spring Boot: 4.0.5</li>
</ul>



<h2 class="wp-block-heading">Try Amper 0.10.0</h2>



<p>To update an existing project, use the <code>./amper update</code> command.</p>



<p>To get started with Amper, check out our <a href="https://jb.gg/amper/get-started" target="_blank" rel="noopener"><em>Getting started</em></a> guide. Take a look at some examples, follow a tutorial, or read the comprehensive user guide depending on your learning style.</p>


    <div class="buttons">
        <div class="buttons__row">
                                                <a href="https://amper.org" class="btn" target="" rel="noopener">Try Amper</a>
                                                    </div>
    </div>







<h2 class="wp-block-heading">Share your feedback</h2>



<p>Amper is still experimental and under active development. You can provide feedback about your experience by joining the discussion in the <a href="https://slack-chats.kotlinlang.org/c/amper" target="_blank" rel="noopener">Kotlinlang Slack’s #amper channel</a> or sharing your suggestions and ideas in a <a href="https://youtrack.jetbrains.com/issues/AMPER" target="_blank" rel="noopener">YouTrack issue</a>. Your input and use cases help shape the future of Amper!</p>
]]></content:encoded>
					
		
		
		<media:content url="https://blog.jetbrains.com/wp-content/uploads/2024/02/amper_vc_1.mp4" medium="video" width="1600" height="1000">
			<media:player url="https://blog.jetbrains.com/wp-content/uploads/2024/02/amper_vc_1.mp4" />
			<media:title type="plain">Amper | The Amper Blog</media:title>
			<media:description type="html"><![CDATA[Amper 0.10.0 is out, and it brings a variety of new features, such as JDK provisioning, custom Kotlin compiler plugins, a Maven-to-Amper converter, and numerous IDE improvements! Read on for all of the details, and see the release notes for the full list of changes and bug fixes.]]></media:description>
			<media:thumbnail url="https://blog.jetbrains.com/wp-content/uploads/2026/03/AMP-social-BlogFeatured-1280x720-1.png" />
			<media:rating scheme="urn:simple">nonadult</media:rating>
		</media:content>
	</item>
		<item>
		<title>KotlinConf’26 Speakers: In Conversation with Josh Long</title>
		<link>https://blog.jetbrains.com/kotlin/2026/03/kotlinconf-26-speakers-in-conversation-with-josh-long/</link>
		
		<dc:creator><![CDATA[Daria Voronina]]></dc:creator>
		<pubDate>Mon, 23 Mar 2026 14:51:05 +0000</pubDate>
		<featuredImage>https://blog.jetbrains.com/wp-content/uploads/2026/03/Blog-Featured.png</featuredImage>		<category><![CDATA[news]]></category>
		<category><![CDATA[interview]]></category>
		<category><![CDATA[josh-long]]></category>
		<category><![CDATA[kotlinconf]]></category>
		<guid isPermaLink="false">https://blog.jetbrains.com/?post_type=kotlin&#038;p=690796</guid>

					<description><![CDATA[“There’s never been a better time to be a JVM or Spring developer.” The Spring ecosystem has evolved dramatically over the past decade, from traditional enterprise applications to microservices, distributed systems, and now AI-powered services. Few people have witnessed that evolution as closely as Josh Long, who has served as Spring’s first Developer Advocate since [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h3 class="wp-block-heading"><em><strong>“There’s never been a better time to be a JVM or Spring developer.”</strong></em></h3>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/josh-long.png" alt="KotlinConf’26 Speakers: In Conversation with Josh Long" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Josh Long, Spring Developer Advocate</h4>
                                                <p><span style="font-weight: 400;">Josh Long is the first Spring Developer Advocate, starting in 2010. Josh is a Java Champion, author of 7 books (including </span><i><span style="font-weight: 400;">Reactive Spring</span></i><span style="font-weight: 400;">) and numerous bestselling video trainings (including </span><i><span style="font-weight: 400;">Building Microservices with Spring Boot Livelessons</span></i><span style="font-weight: 400;"> with Spring Boot co-founder Phil Webb), and an open-source contributor (Spring Boot, Spring Integration, Axon, Spring Cloud, Activiti, Vaadin, and others), a YouTuber (Coffee + Software with Josh Long and his Spring Tips series), and a podcaster (</span><i><span style="font-weight: 400;">A Bootiful Podcast</span></i><span style="font-weight: 400;">).</span></p>
                    </div>
                            </div>
        </div>
    </div>



<p><strong>The Spring ecosystem has evolved dramatically over the past decade, from traditional enterprise applications to microservices, distributed systems, and now AI-powered services. Few people have witnessed that evolution as closely as Josh Long, who has served as Spring’s first Developer Advocate since 2010.</strong></p>



<p><strong>Ahead of <a href="https://kotlinconf.com/workshops/?utm_source=blogpost&amp;utm_medium=referral&amp;utm_campaign=firstspeakers" data-type="link" data-id="https://kotlinconf.com/workshops/?utm_source=blogpost&amp;utm_medium=referral&amp;utm_campaign=firstspeakers" target="_blank" rel="noreferrer noopener">KotlinConf’26</a>, we spoke with Josh about how the Spring community has grown, why Kotlin has become such a natural fit for Spring developers, and why he believes there’s never been a better time to build on the JVM.</strong></p>



<div class="buttons">
        <div class="buttons__row">
            <a class="ek-link jb-download-button" title="Meet Josh Long at KotlinConf’26" href="https://kotlinconf.com/schedule/?utm_source=blog&#038;utm_medium=button&#038;utm_campaign=interview-josh-long&#038;day=2026-05-21&#038;session=03a85869-fa3c-52b4-ad32-05b318e8f3a9" target="_blank" rel="noopener" data-test="blog-article-cta" data-cl="true">Meet Josh Long at KotlinConf’26</a>
         </div>
</div>



<h3 class="wp-block-heading"><strong>Q: You were the first Spring Developer Advocate, starting in 2010. How has the community around Spring changed during that time?</strong></h3>



<p><strong>Josh Long:</strong> Back then, most of the things people built were basically web applications. Nowadays, there are web services and backend server-side applications, and those applications are expected to do many more things.</p>



<p>So, the use cases that people introduce into their applications have grown. Before, Spring was very narrowly focused on the enterprise server-side world. Today, we talk about microservices, distributed computing systems, batch processing, integration, and all kinds of security.</p>



<p>And now we talk about AI.</p>



<p>These used to be different jobs and different career paths, but today they can all be done with Spring very naturally – quite elegantly in a lot of cases, compared to some of the alternatives.</p>



<p>So, the community has changed accordingly. The kinds of things people are doing have expanded, and the community around that has grown as well.</p>



<p>Put another way, it’s not that the people who were doing things in 2010 stopped doing those things. It’s more that people who were doing other kinds of work joined the community.</p>



<p>You see this represented in open-source projects, in language choices, Kotlin, for example, and across the whole ecosystem. It’s this wonderful open-source diaspora.</p>


    <div class="blockquote">
                    <blockquote><p>“<i>The galaxy of things people need to do has grown, and so has the community.</i>”</p></blockquote>
            <div class="blockquote__author">
                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="blockquote__author-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/josh-long.png" alt="KotlinConf’26 Speakers: In Conversation with Josh Long">
                                <div class="blockquote__author-info">
                                                        </div>
            </div>
            </div>



<h3 class="wp-block-heading"><strong>Q: As you mentioned, the Spring and Kotlin teams have worked hard to make sure that Kotlin and Spring Boot are a first-class experience. From your perspective, what makes a language truly first-class within a framework ecosystem?</strong></h3>



<p><strong>Josh:</strong> Spring is a framework built on top of the JVM. Most of Spring itself is written in Java, because Java was the only language people used when we created Spring back in 2001.</p>



<p>But we’ve always tried to excel at integration. We want Spring to be a well-behaved citizen on top of the JVM and the languages that run on it.</p>



<p>If you’re a Java developer, we want Spring to feel natural and idiomatic. Someone who understands Java should look at Spring code and immediately understand what’s going on.</p>



<p>The same is true for all integrations. Spring works with dozens of libraries and technologies, and we want those integrations to feel coherent and consistent.</p>



<p>The same principle applies to languages.</p>


    <div class="blockquote">
                    <blockquote><p>“<i>If we support a language, we want Spring to feel natural for people who already use that language. That’s definitely true for Kotlin.</i>”</p></blockquote>
            <div class="blockquote__author">
                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="blockquote__author-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/josh-long.png" alt="KotlinConf’26 Speakers: In Conversation with Josh Long">
                                <div class="blockquote__author-info">
                                                        </div>
            </div>
            </div>



<p>For the longest time, our goal was simply to be a good citizen on top of these languages. We didn’t expect the languages to adapt to us.</p>



<p>When the relationship between the Spring and Kotlin teams began developing more than ten years ago, we discovered that they were incredibly pragmatic and collaborative. They genuinely wanted Kotlin to work well for Spring developers.</p>



<p>That partnership has been a real honor.</p>



<p>One of my favorite examples is the Kotlin all-open plugin.</p>



<p>In Kotlin, classes are final by default. But frameworks like Spring and Hibernate rely on subclassing.</p>



<p>So normally you’d have to declare everything as <code>open</code>. The Kotlin team solved this by creating a compiler plugin. When you use Spring annotations, the classes are implicitly <code>open</code> behind the scenes.</p>



<p>Developers don’t have to change anything – if you go to start.spring.io, it’s already configured.</p>


    <div class="blockquote">
                    <blockquote><p>“<i>It’s a thousand small changes like this that make it clear the language wants to make Spring developers feel comfortable. I feel warm, grateful, and happy thinking about this wonderful teamwork.</i>”</p></blockquote>
            <div class="blockquote__author">
                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="blockquote__author-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/josh-long.png" alt="KotlinConf’26 Speakers: In Conversation with Josh Long">
                                <div class="blockquote__author-info">
                                                        </div>
            </div>
            </div>



<h3 class="wp-block-heading"><strong>Q: When you’re actually building a Spring application in Kotlin, where does it feel noticeably different from building it in Java?</strong></h3>



<p><strong>Josh:</strong> Spring has DSLs. These DSLs are about as elegant as they can be in Java, but Kotlin has a much more expressive language for designing DSLs. That’s not a controversial thing to suggest – it’s just empirically true.</p>



<p>The Spring team has embraced Kotlin. We actually have Kotlin code in Spring itself. We’ve written parts of Spring in Kotlin.</p>



<p>There are several DSLs that we provide in Java that also have sister DSLs written in Kotlin, and those Kotlin DSLs are much nicer.</p>



<p>For example, Spring Cloud Gateway, functional HTTP routes, and the new BeanRegistrar API in Spring Framework 7. There are lots of them. Spring Security has one as well. They’re everywhere.</p>



<p>It’s just a really nice, elegant little language.</p>



<p>And we’ve essentially done the work of building DSLs twice – once for Java and then again in Kotlin – because we wanted the Kotlin version to feel nice and idiomatic and natural. It feels really good.</p>



<div class="buttons">
        <div class="buttons__row">
            <a class="ek-link jb-download-button" title="Join us at KotlinConf’26" href="https://pretix.eu/jetbrains/kotlinconf2026/c/AdBopK2LB/?utm_source=blog&#038;utm_medium=button&#038;utm_campaign=interview-josh-long" target="_blank" rel="noopener" data-test="blog-article-cta" data-cl="true">Join us at KotlinConf’26</a>
         </div>
</div>



<h3 class="wp-block-heading"><strong>Q: For Kotlin developers who are new to Spring, what’s one misconception they often have, and what’s one feature that usually wins them over? For those who haven’t tried Kotlin yet but are big fans of Spring, why should they give it a shot?</strong></h3>



<p><strong>Josh:</strong> I imagine the misconceptions those developers might have are the same ones anyone might have.</p>



<p>If you’re using Spring, you certainly don’t have to use just Java. Spring has always tried to embrace different languages.</p>


    <div class="blockquote">
                    <blockquote><p>“<i>Kotlin is by far the best story we’ve had there.</i>”</p></blockquote>
            <div class="blockquote__author">
                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="blockquote__author-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/josh-long.png" alt="KotlinConf’26 Speakers: In Conversation with Josh Long">
                                <div class="blockquote__author-info">
                                                        </div>
            </div>
            </div>



<p></p>



<p>People may not realize this, but we had a Spring for Scala project about fifteen years ago. We also tried Groovy. You can still use Groovy today, although I personally never do.</p>



<p>Kotlin is just a really natural fit.</p>



<p>The only language where Spring has actually added that language to the Spring Framework itself, as part of the codebase, is Kotlin.</p>



<p>So, I use Kotlin all the time.</p>



<h3 class="wp-block-heading"><strong>Q: You’ve spent years helping developers navigate new technologies. What excites you most right now about building on the JVM?</strong></h3>



<p><strong>Josh:</strong> First of all, the languages we have on the JVM today are very competitive.</p>



<p>If you&#8217;re building something today, languages like Kotlin are just as concise, small, and efficient as many other modern languages. They’re easy to reason about, but they also come with a lot of additional benefits because they run on the JVM.</p>



<p>The JVM itself is incredibly fast and very scalable. It’s one of the few places where you can have a program that is both very small and very fast.</p>



<p>There used to be a kind of trade-off. If you wanted to write something quickly, you used a scripting language like Python or Perl, at least when I first started working. If you wanted performance, you used something like C++.</p>



<p>But now, with languages like Kotlin running on the JVM, you can have both. You can write programs that are as concise as scripting languages while performing close to native languages.</p>



<p>We live in an amazing time.</p>



<p>There’s a second part to this. Because we have this amazing runtime infrastructure and language ecosystem, people are building incredible tools and frameworks on top of it to support new kinds of applications.</p>



<p>For example, I spend a lot of time talking to people about AI. Spring AI is a really nice way to build AI integrations, agentic systems, and integrations with AI models.</p>


    <div class="blockquote">
                    <blockquote><p>“<i>If you had told me 10 or 15 years ago that we would be writing five-line Spring applications in Kotlin that talk to AI models and do interesting things, I would have laughed. That would have sounded impossible. The world is very different now. There has also never been a better time to be a JVM developer or a Spring developer.</i>”</p></blockquote>
            <div class="blockquote__author">
                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="blockquote__author-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/josh-long.png" alt="KotlinConf’26 Speakers: In Conversation with Josh Long">
                                <div class="blockquote__author-info">
                                                        </div>
            </div>
            </div>



<h3 class="wp-block-heading"><strong>Q: With rapid growth in AI-driven applications, what does building AI-powered systems on the JVM look like today, and where do Kotlin and Spring play a role?</strong></h3>



<p><strong>Josh:</strong> I think people are sometimes misguided about AI.</p>



<p>When people talk about AI, they often mix up two very different use cases.&nbsp;</p>



<p>One involves building and training models. That kind of work often uses tools that don’t really exist on the JVM today.</p>


    <div class="blockquote">
                    <blockquote><p>“<i>Building your own models, training them, and doing data science is a very rare and a small use case compared to what 99% of the ecosystem will be doing, which is integrating these models into their business applications. Most of these models are just REST APIs, which means that this is an integration problem.</i>”</p></blockquote>
            <div class="blockquote__author">
                                    <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" class="blockquote__author-img" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/josh-long.png" alt="KotlinConf’26 Speakers: In Conversation with Josh Long">
                                <div class="blockquote__author-info">
                                                        </div>
            </div>
            </div>



<p>For most applications, leveraging AI is about integrating those models into existing systems, and the JVM has always been extremely good at that.</p>



<p>That’s why enterprises use it – it can talk to anything.</p>



<p>Today, we have Spring AI, which makes it easier to build these integrations. Of course, there are other ecosystems on the JVM that have their own approaches to building AI-based applications.</p>



<p>There are lots of good options.</p>



<p>But the important thing is that the JVM is not just as good as something like Python or TypeScript for building these systems. In many cases, it’s actually much better.</p>



<p>There was a benchmark that came out recently looking at the performance of Model Context Protocol implementations. The JVM came out on top. Spring Boot and Spring AI had the best performance.</p>



<p>They compared implementations in Go, Python, and TypeScript, and the JVM performed the best.</p>



<p>So it’s not just a question of whether you can do this work on the JVM. In many cases, it’s much more performant. We also have better security and stronger integration with existing systems.</p>



<p>It’s a really big opportunity for developers in this ecosystem.</p>



<p>Another thing people often miss is that many AI projects fail because they don’t integrate properly with existing systems.</p>



<p>There was an MIT study that suggested something like 90% of AI integrations fail.</p>



<p>That’s not surprising – many teams build AI workflows as completely separate systems, often in Python, that don’t integrate well with the rest of their infrastructure.</p>



<p>But if you extend the systems where the business logic already lives, which is often on the JVM, things tend to work much better.</p>



<p>If you extend those existing services with tools like Spring AI and Kotlin, you’ll usually have a much better experience.</p>



<p>So it’s not just about being as good as other ecosystems. In many cases, the JVM is simply better for this kind of work.</p>



<p><strong>As Josh notes, many new technologies, including AI, ultimately come down to how well they integrate with the systems developers already use.</strong></p>



<p><strong>Josh will dive deeper into how Kotlin and Spring Boot work together to create a cleaner, more productive developer experience in his <a href="https://kotlinconf.com/schedule/?day=2026-05-21&amp;session=03a85869-fa3c-52b4-ad32-05b318e8f3a9" target="_blank" data-type="link" data-id="https://kotlinconf.com/schedule/?day=2026-05-21&amp;session=03a85869-fa3c-52b4-ad32-05b318e8f3a9" rel="noreferrer noopener">KotlinConf’26 talk “Bootiful Kotlin.”</a></strong></p>



<p><strong>Don’t miss Josh Long at KotlinConf’26!</strong></p>



<div class="buttons">
        <div class="buttons__row">
            <a class="ek-link jb-download-button" title="Join us at KotlinConf’26" href="https://pretix.eu/jetbrains/kotlinconf2026/c/AdBopK2LB/?utm_source=blog&#038;utm_medium=button&#038;utm_campaign=interview-josh-long" target="_blank" rel="noopener" data-test="blog-article-cta" data-cl="true">Join us at KotlinConf’26</a>
         </div>
</div>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>KotlinConf 2026: Talks to Help You Navigate the Schedule</title>
		<link>https://blog.jetbrains.com/kotlin/2026/03/kotlinconf-2026-talks-schedule/</link>
		
		<dc:creator><![CDATA[Jelena Ilic]]></dc:creator>
		<pubDate>Fri, 20 Mar 2026 07:20:54 +0000</pubDate>
		<featuredImage>https://blog.jetbrains.com/wp-content/uploads/2026/03/JB-social-BlogFeatured-1280x720-1-6.png</featuredImage>		<category><![CDATA[news]]></category>
		<category><![CDATA[kotlinconf]]></category>
		<guid isPermaLink="false">https://blog.jetbrains.com/?post_type=kotlin&#038;p=686478</guid>

					<description><![CDATA[The full KotlinConf’26 schedule is finally live, and it’s packed! With parallel tracks, deep-dive sessions, and back-to-back talks, planning your time can feel overwhelming. When almost every session looks interesting, deciding where to spend your time isn’t easy. To help you navigate it all, the Kotlin team has selected a few talks worth adding to [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>The full KotlinConf’26 <a href="https://kotlinconf.com/schedule/?day=2026-05-20" target="_blank" rel="noreferrer noopener">schedule</a> is finally live, and it’s packed!</p>



<p>With parallel tracks, deep-dive sessions, and back-to-back talks, planning your time can feel overwhelming. When almost every session looks interesting, deciding where to spend your time isn’t easy.</p>



<p>To help you navigate it all, the Kotlin team has selected a few talks worth adding to your list. Whether you’re an intermediate or advanced Kotlin developer looking to sharpen your expertise, part of a multiplatform team solving cross-platform challenges, building robust server-side systems, or exploring AI-powered applications in Kotlin, these are sessions you might want to check out.</p>



<div class="buttons">
        <div class="buttons__row">
            <a class="ek-link jb-download-button" title="Join us at KotlinConf’26" href="https://pretix.eu/jetbrains/kotlinconf2026/c/BGsvzd0co/?utm_source=blog&#038;utm_medium=button&#038;utm_campaign=must-see-talks" target="_blank" rel="noopener" data-test="blog-article-cta" data-cl="true">Join us at KotlinConf’26</a>
         </div>
</div>



<h2 class="wp-block-heading">Want more than talks? Start with hands-on practice</h2>



<p>If you prefer learning by doing, consider starting KotlinConf with a full-day hands-on workshop on May 20. Workshops are small-group, code-focused sessions where you can go deeper into topics like Kotlin Multiplatform, coroutines, backend, AI, and more.</p>



<p>Some workshops are already sold out, and others are filling up fast.</p>



<div class="buttons">
        <div class="buttons__row">
            <a class="ek-link jb-download-button" title="View workshops and save your spot" href="https://kotlinconf.com/workshops/?utm_source=email&#038;utm_medium=post&#038;utm_campaign=workshops_2026" target="_blank" rel="noopener" data-test="blog-article-cta" data-cl="true">View workshops and save your spot</a>
         </div>
</div>



<h2 class="wp-block-heading">Intermediate&nbsp;</h2>



<p>These talks are perfect if you want to build on your foundations, understand where Kotlin is heading, and sharpen practical skills you can apply in your day-to-day work.</p>



<h3 class="wp-block-heading"><a href="https://kotlinconf.com/schedule/?day=2026-05-21&amp;session=4a5ad58d-803a-5fdd-b55c-1508768939c7" target="_blank" rel="noreferrer noopener"><strong><em>Evolving Language Defaults</em></strong></a></h3>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/michail-zarecenskij.jpg" alt="" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Michail Zarečenskij</h4>
                                                <p>Kotlin Lead Language Designer, JetBrains</p>
                    </div>
                            </div>
        </div>
    </div>



<p>Programming languages are shaped by their defaults – what’s safe, convenient, and practical. But defaults evolve, and yesterday’s good idea can become today’s source of friction. This session explores how languages rethink and change their defaults, including mutability, null-safety, and deeper object analysis. With examples from C#, Java, Swift, Dart, and Kotlin, you’ll gain insight into how Kotlin continues to evolve and what those changes mean for everyday development.</p>



<h3 class="wp-block-heading"><strong><em><a href="https://kotlinconf.com/schedule/?day=2026-05-21&amp;session=63127f06-ebb6-59e5-8e81-d3afe74c2f36" target="_blank" rel="noreferrer noopener">Real-World Data Science With Kotlin Notebook</a></em></strong></h3>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/adele-carpenter.png" alt="" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Adele Carpenter</h4>
                                                <p>Software Engineer, Trifork Amsterdam</p>
                    </div>
                            </div>
        </div>
    </div>



<p>Data is messy, and drawing the right conclusions takes more than generating a pretty chart. In this practical session, Adele will walk you through analyzing a real-world powerlifting dataset using Kotlin tools. You’ll explore how to understand and validate data, work with Postgres and DataFrame, and visualize results with Kandy – all directly from your IDE. It’s a hands-on introduction to doing thoughtful, reliable data science in Kotlin.</p>



<h3 class="wp-block-heading"><a href="https://kotlinconf.com/schedule/?day=2026-05-21&amp;session=da287f7e-7903-5566-916f-ba7132f4265c" target="_blank" rel="noreferrer noopener"><strong><em>Talking to Terminals (And How They Talk Back)</em></strong></a></h3>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/jake-wharton-1.jpg" alt="" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Jake Wharton</h4>
                                                <div class="wt-row wt-row_size_m kt-offset-top-32">
<div class="wt-col-8 wt-col-md-12 kt-offset-top-8">
<div class="_rs-subtitle-1_1owszn1_1 _rs-text_hardness_auto_1owszn1_1 header-common-section__subtitle kt-text-color-hardness-average">Android Developer, Skylight</div>
</div>
</div>
                    </div>
                            </div>
        </div>
    </div>



<p>Modern terminals can do far more than print text. In this deep dive, Jake explores how command-line apps communicate with terminals – from colors and sizing to advanced features like frame sync, images, and keyboard events. Using Kotlin, he covers OS-specific APIs, JVM vs. Kotlin/Native challenges, and reusable libraries that help you unlock the full power of the terminal.</p>



<h3 class="wp-block-heading"><a href="https://kotlinconf.com/schedule/?day=2026-05-22&amp;session=a3ebeeb9-7a31-5a10-af06-54fc0b1469a3" target="_blank" rel="noreferrer noopener"><strong><em>Dissecting Kotlin: 2026 </em></strong></a></h3>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/huyen-tue-dao.jpg" alt="" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Huyen Tue Dao</h4>
                                                <p>Software Engineer, Netflix<br />
Co-host, Android Faithful</p>
                    </div>
                            </div>
        </div>
    </div>



<p>Ten years after Kotlin 1.0, the language continues to evolve quickly. This talk examines recent stable and preview features, unpacking their design and implementation to reveal what they tell us about Kotlin’s direction. You’ll leave with a deeper understanding of how the language is shaped and how those insights can influence your own Kotlin code.</p>



<h3 class="wp-block-heading"><a href="https://kotlinconf.com/schedule/?day=2026-05-22&amp;session=79d85562-665b-5d9b-b78c-d230bd7d8a37" target="_blank" rel="noreferrer noopener"><strong><em>Full-Stack Kotlin AI: Powering Compose Multiplatform Apps With Koog and MCP </em></strong></a></h3>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/john-oreilly.jpg" alt="" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>John O’Reilly</h4>
                                                <p>Software Engineer, Neat</p>
                    </div>
                            </div>
        </div>
    </div>



<p>This session explores how Koog can power the intelligent core of a Compose Multiplatform app. This session demonstrates building AI-driven applications using local tools across Android, iOS, and desktop, connecting to an MCP server with the Kotlin MCP SDK, and integrating both cloud and on-device LLMs. It’s a practical look at bringing full-stack AI into real Kotlin applications.</p>



<h2 class="wp-block-heading">Advanced</h2>



<p>Ready to go deeper? These sessions dive into compiler internals, language design, architecture, and performance, making them ideal for experienced developers who want to explore Kotlin beneath the surface.</p>



<h3 class="wp-block-heading"><a href="https://kotlinconf.com/schedule/?day=2026-05-21&amp;session=7aacf6ac-eb30-5d7b-89ca-493cfbb0a83d" target="_blank" rel="noreferrer noopener"><strong><em>Metro Under the Hood </em></strong></a></h3>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/zac-sweers.jpg" alt="" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Zac Sweers</h4>
                                                <p>Mobile Person, Kotlin</p>
                    </div>
                            </div>
        </div>
    </div>



<p>Metro is both a multiplatform DI framework and a sophisticated Kotlin compiler plugin. This advanced session breaks down how Metro works inside the compiler, what code it generates, and how its “magic” actually happens. If you’re comfortable with DI frameworks and curious about compiler-level mechanics, this is a rare behind-the-scenes look.</p>



<h3 class="wp-block-heading"><a href="https://kotlinconf.com/schedule/?day=2026-05-21&amp;session=87dec3d9-2f0e-5f37-a651-81b66a84ba25" target="_blank" rel="noreferrer noopener"><strong><em>Local Lifetimes for Kotlin </em></strong></a></h3>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/ross-tate.jpg" alt="" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Ross Tate</h4>
                                                <p>Programming-Languages Researcher and Consultant</p>
                    </div>
                            </div>
        </div>
    </div>



<p>What if Kotlin could enforce that certain objects never escape their intended scope? This talk introduces a proposed design for enforceable locality – lightweight, limited-lifetime objects that prevent leaks and enable safer APIs. Beyond bug prevention, locality opens the door to advanced control patterns, effect-like behavior, and strong backwards compatibility, all while integrating cleanly into today’s Kotlin ecosystem.</p>



<h3 class="wp-block-heading"><a href="https://kotlinconf.com/schedule/?day=2026-05-22&amp;session=f76e512e-a230-57fc-b671-9909f7b13532" target="_blank" rel="noreferrer noopener"><strong><em>Advanced Kotlin Native Integration </em></strong></a></h3>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/tadeas-kriz.jpg" alt="" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Tadeas Kriz</h4>
                                                <p>Senior Kotlin Developer, Touchlab</p>
                    </div>
                            </div>
        </div>
    </div>



<p>Kotlin Multiplatform native builds come with a key constraint: one native binary per project. This session explores what happens when multiple binaries enter the picture, the architectural impact on large systems, and strategies for splitting compilation into manageable parts. It’s a practical look at scaling Kotlin/Native in complex, multi-repository environments.</p>



<h3 class="wp-block-heading"><a href="https://kotlinconf.com/schedule/?day=2026-05-22&amp;session=5634b2b7-199e-5288-bf34-213b33d5b934" target="_blank" rel="noreferrer noopener"><strong><em>Deconstructing OkHttp </em></strong></a></h3>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/jesse-wilson.jpg" alt="" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Jesse Wilson</h4>
                                                <div class="wt-row wt-row_size_m kt-offset-top-32">
<div class="wt-col-8 wt-col-md-12 kt-offset-top-8">
<div class="_rs-subtitle-1_1owszn1_1 _rs-text_hardness_auto_1owszn1_1 header-common-section__subtitle kt-text-color-hardness-average">Programmer</div>
</div>
</div>
<div class="wt-row wt-row_size_m kt-offset-top-64 kt-offset-top-sm-48">
<div class="gatsby-image-wrapper gatsby-image-wrapper-constrained wt-col-4 wt-col-sm-12 speaker-page__speaker-image" data-gatsby-image-wrapper=""></div>
</div>
                    </div>
                            </div>
        </div>
    </div>



<p>Instead of showing how to use OkHttp, this talk opens it up. You’ll explore its interceptor-based architecture, connection lifecycle management, caching state machines, URL decoding, and performance optimizations. From generating HTTPS test certificates to extending the library in multiple ways, this session is a masterclass in reading and learning from high-quality Kotlin code.</p>



<h2 class="wp-block-heading">Multiplatform</h2>



<p>Kotlin Multiplatform continues to expand what’s possible across devices and platforms. These sessions showcase the latest advancements, real-world journeys, and forward-looking tooling shaping the cross-platform landscape.</p>



<h3 class="wp-block-heading"><a href="https://kotlinconf.com/schedule/?day=2026-05-21&amp;session=92678c1e-b1f8-59d7-b035-0e8793896aff" target="_blank" rel="noreferrer noopener"><strong><em>What&#8217;s New in Compose Multiplatform: Better Shared UI for iOS and Beyond</em></strong></a></h3>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/sebastian-aigner.png" alt="" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Sebastian Aigner</h4>
                                                <p>Developer Advocate, JetBrains</p>
                    </div>
                            </div>
        </div>
    </div>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/marton-braun.png" alt="" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Márton Braun</h4>
                                                <p>Developer Advocate, JetBrains</p>
                    </div>
                            </div>
        </div>
    </div>



<p>This session explores what’s new in Compose Multiplatform and how it continues to improve shared UI across iOS, web, desktop, and Android. You’ll get a hands-on look at recent platform advances, including faster rendering, improved input handling, richer iOS interop, web accessibility improvements, and a smoother developer experience with unified previews, mature Hot Reload, and a growing ecosystem. It’s a practical update on how Compose Multiplatform is becoming an even stronger choice for cross-platform UI.</p>



<p>If you&#8217;re interested in going deeper into Compose Multiplatform, there is also a <a href="https://kotlinconf.com/workshops/?utm_source=email&amp;utm_medium=post&amp;utm_campaign=workshops_2026#shared-ui-with-compose-multiplatform" data-type="link" data-id="https://kotlinconf.com/workshops/?utm_source=email&amp;utm_medium=post&amp;utm_campaign=workshops_2026#shared-ui-with-compose-multiplatform" target="_blank" rel="noopener">hands-on workshop</a> where you can build shared UI across platforms and work directly with architecture, state, and real-world app patterns.</p>



<h3 class="wp-block-heading"><a href="https://kotlinconf.com/schedule/?day=2026-05-22&amp;session=e5f8f1a7-d8f0-5a73-9d1e-adcaece373f4" target="_blank" rel="noreferrer noopener"><strong><em>Sony’s KMP Journey: Scaling BLE and Hardware With Kotlin Multiplatform</em></strong></a></h3>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/sergio-carrilho.png" alt="" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Sergio Carrilho</h4>
                                                <p>TechLead, Sony</p>
                    </div>
                            </div>
        </div>
    </div>



<p>Go behind the scenes of Sony’s six-year journey from an early, risky experiment with Kotlin Multiplatform to the global success of the Sony | Sound Connect app. From high-speed BLE and background execution to migrating from React Native to Compose Multiplatform, this talk explores technical trade-offs, stakeholder skepticism, and hard-earned architectural lessons. It’s a real-world story of betting on KMP early and scaling it globally.</p>



<h3 class="wp-block-heading"><a href="https://kotlinconf.com/schedule/?day=2026-05-21&amp;session=8ad5085d-1b01-5df1-aee2-edf629b20a50" target="_blank" rel="noreferrer noopener"><strong><em>Swift Export: Where We Stand </em></strong></a></h3>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/pamela-hill.jpg" alt="" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Pamela Hill</h4>
                                                <p>Developer Advocate, JetBrains</p>
                    </div>
                            </div>
        </div>
    </div>



<p>Swift Export aims to make calling shared Kotlin code from Swift more idiomatic and natural. This session looks at the current experimental state of Swift Export, demonstrates the transition from the old Objective-C bridge to the new approach, and highlights supported features, current limitations, and practical adoption guidance. By the end, you’ll be able to evaluate whether Swift Export is ready for your team.</p>



<h3 class="wp-block-heading"><a href="https://kotlinconf.com/schedule/?day=2026-05-22&amp;session=dd67b894-f260-58e3-a9ad-f65bc6cbcec0" target="_blank" rel="noreferrer noopener"><strong><em>Practical Filament – Reshape Your UI! </em></strong></a></h3>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/nicole-terc.jpg" alt="" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Nicole Terc</h4>
                                                <p>SWE, HubSpot</p>
                    </div>
                            </div>
        </div>
    </div>



<p>Discover how Filament, a real-time physically-based rendering engine, can bring dynamic visual effects into your Compose Multiplatform UI. Through practical examples, you’ll explore materials, shaders, lighting, and touch-reactive animations – all without diving too deep into low-level graphics code. It’s a hands-on introduction to building expressive, animated interfaces.</p>



<h3 class="wp-block-heading"><a href="https://kotlinconf.com/schedule/?day=2026-05-21&amp;session=ff991eb0-f2fb-5f0d-b983-3917ed846981" target="_blank" rel="noreferrer noopener"><strong><em>Kotlin/Wasm: Finally, the Missing Piece for a Full Stack Kotlin Webapp! </em></strong></a></h3>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/dan-kim.jpg" alt="" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Dan Kim</h4>
                                                <p>Engineering Manager</p>
                    </div>
                            </div>
        </div>
    </div>



<p>With Kotlin/Wasm reaching Beta and supported in modern browsers, full-stack Kotlin is closer than ever. This talk walks through building a complete web app using Kotlin/Wasm, Compose Multiplatform, Coroutines, Exposed, and Ktor – unifying the frontend, backend, and database in one ecosystem. It’s a practical guide to building performant, fully Kotlin-powered web applications.</p>



<h2 class="wp-block-heading">Server-side</h2>



<p>Kotlin is increasingly used to power large-scale backend systems. These talks explore how Kotlin powers high-performance systems, large migrations, and mission-critical platforms in the real world.&nbsp;</p>



<p>Prefer hands-on backend work? A <a href="https://kotlinconf.com/workshops/?utm_source=email&amp;utm_medium=post&amp;utm_campaign=workshops_2026#spring-boot-with-coroutines-and-virtual-threads" data-type="link" data-id="https://kotlinconf.com/workshops/?utm_source=email&amp;utm_medium=post&amp;utm_campaign=workshops_2026#spring-boot-with-coroutines-and-virtual-threads" target="_blank" rel="noopener">KotlinConf workshop</a> covers building high-performance APIs with coroutines and Spring Boot.</p>



<h3 class="wp-block-heading"><a href="https://kotlinconf.com/schedule/?day=2026-05-21&amp;session=eefcaa12-46b9-5575-a129-a37c793b4c29" target="_blank" rel="noreferrer noopener"><strong><em>How Google.com/Search Builds on Kotlin Coroutines for Highly Scalable, Streaming, Concurrent Servers </em></strong></a></h3>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/sam-berlin.jpg" alt="" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Sam Berlin</h4>
                                                <div class="wt-row wt-row_size_m kt-offset-top-32">
<div class="wt-col-8 wt-col-md-12 kt-offset-top-8">
<div class="_rs-subtitle-1_1owszn1_1 _rs-text_hardness_auto_1owszn1_1 header-common-section__subtitle kt-text-color-hardness-average">Senior Staff Software Engineer, Search Infra, Google</div>
</div>
</div>
<div class="wt-row wt-row_size_m kt-offset-top-64 kt-offset-top-sm-48">
<div class="gatsby-image-wrapper gatsby-image-wrapper-constrained wt-col-4 wt-col-sm-12 speaker-page__speaker-image" data-gatsby-image-wrapper=""></div>
</div>
                    </div>
                            </div>
        </div>
    </div>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/alessio-della-motta.png" alt="" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Alessio Della Motta</h4>
                                                <p>Senior Staff Software Engineer, Search Infra, Google</p>
                    </div>
                            </div>
        </div>
    </div>



<p>Discover how Google Search uses server-side Kotlin and coroutines to enable low-latency, highly asynchronous streaming code paths at massive scale. This session explores Qflow, a data-graph interface language connecting asynchronous definitions with Kotlin business logic, along with coroutine instrumentation for latency tracking and critical path analysis. It’s a deep look at building “asynchronous by default” systems at massive scale.</p>



<h3 class="wp-block-heading"><a href="https://kotlinconf.com/schedule/?day=2026-05-21&amp;session=81ca2bb9-7797-5b13-aa65-87d9143614ca" target="_blank" rel="noreferrer noopener"><strong><em>Go Get It, With Kotlin: Evolving Uber’s Java Backend</em></strong></a></h3>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/ryan-ulep.jpg" alt="" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Ryan Ulep</h4>
                                                <p>Tech Lead, Developer Platform, Uber</p>
                    </div>
                            </div>
        </div>
    </div>



<p>Uber introduced Kotlin into its massive Java monorepo to modernize backend development without disrupting scale. This talk shares how the JVM Platform team built the business case, addressed tooling and static analysis gaps, overcame skepticism, and enabled thousands of engineers to adopt Kotlin. It’s a practical story of large-scale language evolution inside a global engineering organization.</p>



<h3 class="wp-block-heading"><a href="https://kotlinconf.com/schedule/?day=2026-05-22&amp;session=a0fd8dc7-05c3-5dbb-802b-d788c0315212" target="_blank" rel="noreferrer noopener"><strong><em>Kotlin Bet for Mission-Critical Fintech: Reliability, ROI, Risk, and Platform Architecture </em></strong></a></h3>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/yuri-geronimus.png" alt="" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Yuri Geronimus</h4>
                                                <p>Tech leader, Verifone</p>
                    </div>
                            </div>
        </div>
    </div>



<p>Adopting Kotlin in a payment platform is a strategic decision about risk, trust, and long-term ROI. This session examines how Kotlin was integrated into a global EMV/PCI ecosystem – from Android terminals to gateways – using null-safety, sealed hierarchies, and value classes to eliminate entire classes of production issues. You’ll see architectural outcomes, measurable compliance gains, and a practical framework for positioning Kotlin as a strategic bet in regulated industries.</p>



<h2 class="wp-block-heading">AI</h2>



<p>AI is rapidly becoming part of modern application development. If you’re exploring agents, LLM integrations, or AI-assisted coding, these sessions will give you both strategy and hands-on insight.</p>



<h3 class="wp-block-heading"><a href="https://kotlinconf.com/schedule/?day=2026-05-22&amp;session=3164c0cb-9d95-54a2-bf0a-535e70a7bbfa" target="_blank" rel="noreferrer noopener"><strong><em>Eval-Driven Development: The Fine Line Between Agentic Success and Failure</em></strong></a></h3>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/urs-peter.png" alt="" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Urs Peter</h4>
                                                <p>Senior Software Engineer, JetBrains certified Kotlin Trainer</p>
                    </div>
                            </div>
        </div>
    </div>



<p>Agentic systems introduce probabilistic behavior and real risk. This talk introduces Eval-Driven Development (EDD), an engineering-first approach to making AI agents reliable. Using Koog, you’ll see how to test agents at multiple layers, collect meaningful metrics, detect regressions, generate synthetic test cases with LLMs, and build continuous evaluation loops that prevent silent degradation in production.</p>



<h3 class="wp-block-heading"><a href="https://kotlinconf.com/schedule/?day=2026-05-21&amp;session=5833fd80-ca10-5878-bf3e-290dadfc042b" target="_blank" rel="noreferrer noopener"><strong><em>Why Do Most AI Agents Never Scale? Building Enterprise-Ready AI With Koog </em></strong></a></h3>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/vadim-briliantov.jpg" alt="" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Vadim Briliantov</h4>
                                                <p>Technical Lead of Koog, JetBrains</p>
                    </div>
                            </div>
        </div>
    </div>



<p>Many AI agents fail when moving beyond demos. This session introduces Koog 1.0.0-RC and explains how its structured, type-safe architecture enables scalable, production-ready agents across JVM and KMP targets. You’ll explore cost control, strongly typed workflows, state persistence, observability with OpenTelemetry and Langfuse, and integrations across the Kotlin ecosystem – all focused on building agents that actually scale.</p>



<p>You can also explore these topics in a <a href="https://kotlinconf.com/workshops/?utm_source=email&amp;utm_medium=post&amp;utm_campaign=workshops_2026#building-ai-agents-in-kotlin-with-Koog" data-type="link" data-id="https://kotlinconf.com/workshops/?utm_source=email&amp;utm_medium=post&amp;utm_campaign=workshops_2026#building-ai-agents-in-kotlin-with-Koog" target="_blank" rel="noopener">full-day workshop</a> focused on building AI agents in Kotlin with Koog.</p>



<h3 class="wp-block-heading"><a href="https://kotlinconf.com/schedule/?day=2026-05-21&amp;session=f085c0af-660b-5601-b777-39538bcf73b5" target="_blank" rel="noreferrer noopener"><strong><em>Increasing the Quality of AI-Generated Kotlin Code </em></strong></a></h3>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/sergei-rybalkin.jpg" alt="" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Sergei Rybalkin</h4>
                                                <p>Kotlin, Meta</p>
                    </div>
                            </div>
        </div>
    </div>



<p>Improving AI-generated Kotlin code requires more than better prompts. This talk explores practical strategies, evaluation techniques, and lessons from advancing Kotlin code generation in real-world agents. You’ll learn how to measure quality, refine outputs, and apply tools and best practices that ensure reliability, readability, and maintainability, even as models continue to evolve.</p>



<h3 class="wp-block-heading">Take it further with a workshop</h3>



<p>If you want to go beyond talks and build things yourself, workshops take place on May 20, the day before the conference.</p>



<p>They’re hands-on, small-group sessions led by Kotlin experts — and seats are limited.</p>



<div class="buttons">
        <div class="buttons__row">
            <a class="ek-link jb-download-button" title="View workshops and save your spot" href="https://kotlinconf.com/workshops/?utm_source=email&#038;utm_medium=post&#038;utm_campaign=workshops_2026" target="_blank" rel="noopener" data-test="blog-article-cta" data-cl="true">View workshops and save your spot</a>
         </div>
</div>



<p>This is just a glimpse of the many great sessions waiting for you at KotlinConf’26. With dozens of talks across multiple tracks, the hardest part might simply be choosing which ones to attend. Don’t forget to dive into the full schedule, plan your agenda, and get ready for three days packed with ideas, insights, and conversations with the global Kotlin community.</p>



<div class="buttons">
        <div class="buttons__row">
            <a class="ek-link jb-download-button" title="Browse the full schedule" href="https://kotlinconf.com/schedule/?utm_source=blog&#038;utm_medium=button&#038;utm_campaign=must-see-sessions&#038;day=2026-05-21" target="_blank" rel="noopener" data-test="blog-article-cta" data-cl="true">Browse the full schedule</a>
         </div>
</div>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
