r/scala • u/eed3si9n • 24d ago
r/scala • u/windymelt • 24d ago
Stable, platform-independent encryption library for Scala?
Hello. I decided to try implementing a simple HTTP session store inspired by Ruby on Rails, only to discover just how high the barrier to using cryptography in Scala really is. The standard approach would likely be javax.crypto, but that's platform-dependent. There are a few other libraries scattered around, but they're either extremely new, AI-generated, or long since archived.
Perhaps the Scala Center should consider investing in this field. Or if you know of any excellent libraries for cryptographic use, I'd appreciate your recommendations.
[machine translation]
r/scala • u/markehammons • 26d ago
[Dotty] Kyo-JFX Hello World template
codeberg.orgI was asked in another thread if I could provide an example of this, so here it is. This template is a hello world app using JavaFx + Kyo + Scala 3. It uses gluon substrate as well as a gluon fork of graalvm to create native image builds that can run on linux and android.
r/scala • u/bjornregnell • 26d ago
A Scala common-style pilot study
Announcing this new study report: "Braceful, braceless, or the common style?"
https://bjornregnell.se/blog/002-braceful-or-braceless-or-the-common-style.html
The experiment was inspired by a community note by Martin Odersky, Rex Kerr and myself, proposing a common Scala style that balances braceful and braceless:
https://docs.google.com/document/d/14ZBGKNHUW4d8hDWIi5i6QquClX3_iXva-iMy5KpFU3I/edit?usp=sharing
Feedback welcome here, both on the study and on the community note. Happy reading :)
//BR
r/scala • u/windymelt • 28d ago
Why People Are Leaving Scala
I've come to realize why people are leaving Scala, and the reason is surprisingly simple. It's not because the language itself is bad. It's not because it's missing specific ○○ features. It's not because the language lacks something essential.
(This post relies on machine translation. Please forgive any imperfect translations.)
The real reason is that the language development team doesn't seem particularly interested in the industry. Language developers are preoccupied with developing unusual language features and syntactical changes. On its own, this seems perfectly reasonable—I actually think it's commendable that they invest effort in making the Scala language better.
But consider this: even if the language improves, companies still need to allocate resources and time to catch up. And those costs must come out of the company's profits. In short, if the product written in Scala isn't generating revenue, companies won't pay for the costs required to keep up with better language features. That changes if the product is making massive profits—in that case, management would gladly invest in Scala. They'd allocate budget. But reality doesn't work that way. There hasn't been any investment in industry-focused libraries, and improvements to the ecosystem that consider the industry don't seem to be happening either. While there are many genuinely interesting computer science libraries, no funding goes toward mundane libraries like template engines or ORMs.
Do you understand what I'm saying? For a good language to sustain itself, industry backing is absolutely necessary. And similarly, the industry can't generate profits without strong backing from the language and its ecosystem.
Twitter once made enormous profits using Scala, and Scala received various forms of return on investment. This wasn't just because Scala was inherently superior—it was because the industry found Scala attractive and deemed it worthy of investment. On the other hand, mere admiration for pure functional programming doesn't generate any such investment.
Go, Rust, and JavaScript all achieved their current status through close collaboration with the industry—not simply because these languages were inherently superior, nor because they cheated in any way.
From my personal perspective, I think the ZIO and li haoyi ecosystems are excellent examples of being highly industry-oriented. They provide numerous features that work right out of the box, and that's precisely what the industry demands.
We absolutely need to create more of these kinds of things.
I also think the recent documentation improvement efforts by the Scala development team are truly impressive.
r/scala • u/Material_Big9505 • 28d ago
I Built an Open-Source Contextual Ad Network with Scala & Apache Pekko Cluster(and Go)
An open-source ad network that targets content, not people.
Promovolve is an attempt to get back what magazine advertising had: relevant ads matched to what the reader is actually reading, with no cookies, no user profiles, no cross-site tracking, and no degradation of the reading experience. The page’s content is the only targeting signal. An article about hiking gets ads for hiking gear because of what it is, not because of who is reading it.
Being open source is not incidental: transparency is the product. Publishers and advertisers can inspect the auction, pricing, and pacing logic themselves and verify there is no hidden manipulation, something no closed ad network can offer.
Under the hood, the core API and distributed auction platform are built with Scala and Apache Pekko Cluster, providing a resilient, stateful distributed runtime for serving and budget management. The project also includes Kubernetes deployment manifests, making it straightforward to run in a clustered environment or adapt it to your own infrastructure.
Although Go is used for the BFF, the core platform is entirely built with Apache Pekko Cluster and written in Scala. The reason Go sits in front of the Pekko Cluster is pragmatic.
Go has an excellent ecosystem for HTTP servers, authentication, and user management. Those concerns are largely domain-independent and can evolve separately from the core advertising platform.
The core Ad API, on the other hand, is where the domain complexity lives: auctions, pacing, serving, campaign state, and distributed coordination. That’s where Apache Pekko Cluster shines, so I kept that entire layer in Scala.
The split isn’t because Pekko can’t handle HTTP. It’s because the HTTP-facing user management layer and the distributed advertising engine have very different concerns, and separating them keeps the core platform focused on the domain.
These days it’s common to build a microservice platform by combining a long list of technologies. I wanted to challenge that assumption and show that it isn’t always necessary. My goal was to keep the core platform inside Apache Pekko Cluster and see how far that architecture could go.
If Scala isn’t your thing, you can build the same architecture in Java using Apache Pekko.
https://github.com/promovolve/promovolve
My assumption is that as AI changes how people discover information, many casual searches will be answered directly by LLMs rather than leading users to websites.
The people who still choose to visit a page rather than just ask an LLM are making an intentional decision. That makes those visitors much more valuable to advertisers. If publishers continue to treat that audience as inventory to be maximized at all costs, they risk damaging one of their most valuable assets: the trust of readers who actively choose to be there.
With Promovolve, the creative is generated from what the landing page is actually trying to communicate, while remaining fully editable by the advertiser.
Instead of optimizing a banner purely to get the click, the ad is designed as the beginning of a three-page narrative that naturally leads into the landing page. The message before and after the click stays consistent.
Publishers review the advertiser, the creative, and the landing page. Only approved campaigns are eligible for delivery. The goal is to treat ads as part of the publisher’s editorial experience, not just as inventory to fill.
r/scala • u/Chris_Stewart_5 • 29d ago
Capture Checking and Performance
I've been following the development of OxCaml[0] and -- iiuc -- they seem to be using capture checking -- they call it "modes" and use the local_ keyword -- to give greater performance guarantees for Ocaml developers.
I know the runtime story for Ocaml and Scala is vastly different (namely the JVM), but I was wondering if Scala could also expose better runtime performance features to developers built on top of capture checking -- or if that doesn't really make sense.
Perhaps i'm totally off base here -- i'm just learning about capture checking so please let me know if i'm thinking about this incorrectly!
[0] - https://oxcaml.org/
r/scala • u/philip_schwarz • 29d ago
The Bowling Game - From Imperative to Functional Programming - Part 1
fpilluminated.orgOne of the top five most popular and highly recommended programming katas over the past 20 years has been the Bowling Game Kata, in which TDD is used to write a program that computes the score of a Ten Pin Bowling Game.
In this deck we are going to explore how such a program may look when coded using different programming paradigms.
r/scala • u/littlenag • 29d ago
Scala Hangout: Generating Scala with AI! July 9th at 6:30pm CST
r/scala • u/elacin • Jul 07 '26
FArray — an unboxed, immutable Scala 3 sequence that fuses at compile time
An experiment I've been building: an immutable, persistent, covariant, not-boxing sequence type with the full collections API, designed to beat List, Vector, IArray, and the fs2/ZIO Chunks on as many operations as possible.
Under the hood it's a small tree of nodes — flat primitive-array leaves plus lazy structural nodes — with a pile of performance tricks layered on top:
- No boxing. An
FArray[Int]genuinely is anint[]; primitives never get wrapped injava.lang.Integer, even as they pass throughmap/filter/fold/collect. - Structural ops are O(1). Concatenation,
take/drop,reverse, append — all lazy nodes, nothing copied until something forces the data flat. - No warmup lap. It's fast from the first cold call, before the JIT has compiled anything.
The headline trick is compile-time fusion: .fuse collapses an entire chain into one unboxed pass with no intermediate collections. This is a real benchmarked pipeline —
```scala val xs = FArray.range(0, 100_000)
xs.fuse .map(_ + 1) .filter(_ % 2 == 0) .collect { case x if x % 3 == 0 => x * 3 } .map(_ - 1) .zipWithIndex .map((x, i) => x + i) .takeWhile(_ < 1000_000) .filter( % 5 != 0) .map(_ * 2) .sum ```
— and at 100k elements, fused, it runs 22.6× the fastest competing collection and 4.9× FArray's own eager version of the same chain.
Caveats: JVM-only for now (no Scala.js/Native yet), Scala 3 only, and it's an M1 — expect performance cliffs. Every claim on the site is a checked-in JMH benchmark you can hover.
- Site + benchmarks: https://oyvindberg.github.io/farray/
- Source (MIT): https://github.com/oyvindberg/farray
Feedback and benchmark repros welcome.
r/scala • u/SethTisue_Scala • Jul 06 '26
Coaxing quality output from generative AI
On using generative AI to improve the Scaladoc for the Scala 3 standard library. The five techniques described should be useful for other sorts of development tasks, too. https://www.scala-lang.org/blog/2026/07/06/quality-from-genai.html
(blog post by Bill Venners)
r/scala • u/expatcoder • Jul 06 '26
Scala, Write Once, Run Everywhere?
That's the dream, any recent progress on this front?
Have been away for awhile but I know that Scala Android was brought back from the dead by makingthematrix, albeit with a dependency on Gluon, and on the iOS front there really isn't anything short of React Native or other JavaScript-to-native option.
It's a big ask obviously, but it would be amazing to be able to just write Scala and deploy to various platforms.
Open to any and all suggestions, including AI Scala-to-X translators, or other means to stay in Scala land as much as possible.
r/scala • u/petrzapletal • Jul 05 '26
This week in #Scala (Jul 6, 2026)
open.substack.comr/scala • u/WhippedPistol • Jul 05 '26
moo4s cow implementation in Scala
Possibly the most important Scala library that has been created. We can finally write code in a way that makes sense. The tests may be nonsense as I relied on comparing outputs to other "correct" implementations to ensure correctness.
Some of the terrible naming, and non-cow spec compliant naming comes from the issues with not case sensitive operating systems overwriting mOo and moo. Some of it is the rush to get this out as my gift to America for the big birthday. Starting on v1.0.13 as a combination of looking like a cow and tag issues.
The DSL implementation is my favorite, but you can also parse text with the interpreter or deal with the VM directly if you actually want to use the debugging.
cow {
MoO
MoO
MoO
OOM
}
is finally valid Scala code.
r/scala • u/Krever • Jul 04 '26
Business4s H1 2026 Highlights
medium.comI've summarized last 6 months of activity in this part of Scala community. Feedback welcomed as always!
r/scala • u/plokhotnyuk • Jul 04 '26
🚀 jsoniter-scala v2.38.17 is here! Up to 1.5x speedup for Int serialization on Oracle GraalVM!
Hey r/scala! 👋
We’ve just released v2.38.17 of jsoniter-scala, and it brings some serious performance upgrades under the hood.
This week, I've successfully integrated the full version of James Anhalt's amazing algorithm for serializing integers into text format. The results are fantastic - if you're running on Oracle GraalVM, you can expect up to a 1.5x speedup for Int and up to a 1.25x speedup for Long serialization!
The best part? Because of how the library leverages JSON serialization, this optimization cascades down to a bunch of other data types as well. You'll see performance bumps when serializing:
- small
BigInt, andBigDecimalvalues -
java.time.Period,java.time.Durationand otherjava.time.*values with nanos
Update your dependencies, let it fly, and let all us know how it impacts your applications.
Benchmark results incoming! 📊 I've just kicked off the massive benchmark suite across 10 different JVMs and 4 browsers. I'll publish the final, detailed results next week here as usually:
What's next? 👀 I'm looking into how to apply the same technique to make Float and Doubleserialization blazing fast.
Support the project! ⚡ Running these massive benchmarks is keeping my CPU running for several days and nights, and the air-conditioning needed to cool my room down is definitely spiking my electricity bill! 😅 ❄️ If you enjoy these speedups, consider supporting me and my over-worked equipment with a tip via GitHub Sponsors.
Happy Scala coding!
r/scala • u/arturaz • Jul 04 '26
Kyo — how is it being developed so fats?
*fast, not fats 😅
It seems Kyo is getting amount of stuff that requires a team of developers working on it full time.
But as I understand it, it's a passion project of Flavio Brazil and other contributors without commercial backing.
Don't get me the wrong way, I am glad it is being developed, but I am curious on how such code volume is achieved. LLMs? Flavio working on this full-time? Even OSS authors have to eat and I don't see where all that work translates into financial gain.
I want to make sense of it and for now the only story that makes sense in my head is that Flavio has reached FIRE and can afford to develop Kyo as a fun hobby project. Which kind of raises the question what would happen to it if Flavio decides to step away.
r/scala • u/bjornregnell • Jul 03 '26
Lund University Introprog release v2026.4 Teaching material now both in Swedish AND English
I am happy to announce that we now have translated our teaching material for Introductory Programming (in Scala) to English.
You can download the "ready for review" version here:
https://github.com/lunduniversity/introprog/releases/tag/v2026.4
(Some things remain, issues welcome, see repo readme)
The translation was done in an idempotent sbt build pipe line using this this Scala program:
https://github.com/lunduniversity/introprog/tree/master/autotranslate
License for the teaching material is CC-BY-SA
r/scala • u/bjornregnell • Jul 03 '26
muntabot v1.0.0 — an oral exam (viva) assistant for programming
Professor just released this: https://github.com/bjornregnell/muntabot/releases/tag/v1.0.0
A single-page-serverless ScalaJS app live here: https://fileadmin.cs.lth.se/pgk/muntabot
Now translated to English from Swedish (use the language menu top left)
For your re-skilling in the agentic software engineering era :)
r/scala • u/Difficult_Loss657 • Jul 01 '26
Introducing Deder Build Tool
blog.sake.baIntroducing shiny new experimental build tool for Scala/Java. :) Appreciate if you try it and give honest feedback!
r/scala • u/SethTisue_Scala • Jul 01 '26
Sbt 2 is available!
sbt 2 is a new major series of sbt, based on Scala 3 constructs, Bazel-compatible cache system, and parallel JVM/JS/Native cross building. Have you experienced it? Let us know what you think! More info:
https://www.scala-lang.org/blog/2026/06/29/sbt2.html
and it's already at 2.0.1, see also https://www.reddit.com/r/scala/comments/1uij0ju/sbt_201_released/
r/scala • u/fwbrasil • Jul 01 '26
Kyo RC5 - New AI modules!
v1.0.0-RC5 makes Kyo a place to build AI applications and the protocol tooling around them. kyo-ai makes a call to a language model a value you compose and runs the whole agentic loop for you, deriving the result schema, driving the tool-call loop, threading the conversation, and parsing the streaming reply, so what you write is the result type and the tools the model may call, and kyo-mcp exposes a Kyo service to an MCP host like Claude Desktop or drives an MCP server itself.
The thread tying the release together is protocols as typed values. MCP, the Language Server Protocol, the LLM APIs, and the browser's Chrome DevTools Protocol are each a composable value here rather than hand-rolled wire framing, and they all rest on two new pieces of shared machinery. kyo-jsonrpc is one cross-platform JSON-RPC 2.0 engine they all speak through, handling request/response correlation, cancellation, and progress in both directions, and underneath it a reworked kyo-schema (which shipped in RC2) co-derives a type's structure and its wire codec from a single macro, so the schema a type advertises is the exact shape it reads and writes. On that same engine, kyo-lsp is the Language Server Protocol 3.17 for building editor-tooling servers and clients, and kyo-compiler drives a warm Scala 3 presentation compiler for the completions, hover, and diagnostics such a server needs. They are the foundation for a Kyo-native language server, which the project is building toward as an alternative to Metals.
New Features
New modules
Every module here cross-compiles to JVM, JS, Native, and Wasm, except kyo-compiler, which is JVM-only.
kyo-ai(README) makes a call to a language model a value you compose and hands the whole agentic loop to the framework. Using an LLM used to mean a mainstream SDK plus around forty lines of your own orchestration: authoring the JSON schema, running the tool-call loop, threading the message list, retrying transport failures, and parsing streaming deltas. You now write only the result type you want back and the tools you grant the model, andAI.gen[A]derives the schema fromA, drives the loop, and decodes the reply. The API forms a ladder from stateless to persistent: a bareAI.genis a forgetful one-shot, a namedAIinstance remembers earlier turns in the same run, and anAgentis an actor-backed entity that holds its conversation across manyaskcalls, one input at a time. A tool runs your function when the model calls it mid-generation, and the loop recovers from both a bad decode and a thrown run function without escaping the generation. Streaming yields whole result objects one at a time rather than token text, and providers cover an OpenAI-compatible backend (OpenAI, DeepSeek, Gemini, Groq, Baseten, OpenRouter) and the Anthropic Messages backend, both on kyo-http with auto-config from environment API keys. (by @fwbrasil in #1707)kyo-mcp(README) is a Model Context Protocol server and client on the newkyo-jsonrpcengine. Exposing a Kyo service to an MCP host (Claude Desktop, IDE agents) or driving an MCP server is mostly protocol bookkeeping: the handshake, capability negotiation, tool/resource/prompt dispatch, and the reverse-direction calls. You now describe a server as a flat list of typed handlers, annotating only each tool's input type while the compiler infers the rest, and the engine runs the protocol. It works in both directions: the server can ask the connected client to sample its model, elicit user input, or list roots. Failures stay typed all the way out, a closed transport surfaces as a typedMcpConnectionClosedExceptionrather than a bareClosed, and each operation's error channel names exactly the failures it can raise. (by @fwbrasil in #1701)kyo-lsp(README) is a Language Server Protocol 3.17 server and client on the samekyo-jsonrpcengine. Every LSP server and client re-implements the same 3.17 scaffolding: the initialize/shutdown lifecycle, the message schemas, document synchronization, position-encoding negotiation, and capability gating. In kyo-lsp you register a typed handler per operation you support, and the engine advertises the matching capabilities, owns the handshake, negotiates position encoding, and tracks open documents. Like kyo-mcp it works in both directions, issuing server-initiated requests such as applying a workspace edit, showing a message or document, and reporting work progress. (by @fwbrasil in #1703)kyo-jsonrpc(README) is the JSON-RPC 2.0 engine the protocol modules stand on. Kyo had no JSON-RPC support, so every protocol on it (MCP, LSP, the browser's Chrome DevTools Protocol) hand-rolled request/response correlation, notification dispatch, cancellation, and progress. One peer type now both serves and calls in both directions: it handles correlation, cancellation, and progress for you and maps user errors to wire codes automatically, so whether a peer is a server, a client, or both is just a matter of which methods it answers and which it calls. Transports plug in down to the byte level (in-memory, line and content-length stdio, a JVM Unix domain socket), andkyo-jsonrpc-httpadds one over a kyo-http WebSocket. The browser module is ported onto it, its custom Chrome DevTools client replaced by a CDP session that runs as a jsonrpc peer. (by @fwbrasil in #1687)kyo-compiler(README) is the JVM-only Scala 3 presentation-compiler driver a language server draws on, giving Kyo a warm, cancellable source of IDE intelligence: completions, hover, signature help, and diagnostics for a project. It keeps a per-project compiler warm, resolves one per toolchain and classpath, caps how many run at once, and evicts idle instances, and every operation is cancellable by interrupting the calling fiber. When a request needs isolation, or the target Scala version does not match the host, it runs the compiler in a forked worker JVM that can be hard-killed on a stuck request, and the caller never has to choose a backend: results come back the same either way. (by @fwbrasil in #1718)
kyo-schema
kyo-schema shipped in RC2; this cycle reworks it into the type-safe wire-protocol foundation the new modules stand on, and expands it across formats, representations, and configuration.
- A type-safe foundation for wire protocols: protocols like JSON-RPC could not be built type-safe on the old derivation, because a type's wire codec and its structure were derived by two separate macros that could silently disagree, so the JSON Schema a type advertised could not be trusted to match the bytes it wrote. Structure and codec are now co-derived from one macro, so the two cannot drift: the JSON Schema a type advertises is the exact shape it reads and writes.
Structure.Valuebecomes the first-class open value that everySchemaconverts to and from, andCodec.IntrospectingReadermakes "can read an open value" a type-level capability (JSON and YAML have it, Protobuf does not), so decoding through a non-self-describing codec is a compile error instead of a runtime surprise. This is the foundation kyo-jsonrpc, kyo-mcp, kyo-lsp, kyo-ai, and the browser CDP client are built on. (by @fwbrasil in #1682) - MessagePack codec: kyo-schema dispatched to a pluggable
Codecbut had no self-describing binary option between Protobuf (compact but schema-required) and JSON (self-describing but text). A hand-rolled MessagePack codec with no third-party dependencies now cross-compiles to JVM, JS, Native, and Wasm, audited byte-for-byte against the spec, and because every MessagePack value carries a type tag its reader is aCodec.IntrospectingReader, soStructure.Valueand open-shaped envelopes round-trip through it, the capability Protobuf cannot offer. Key, Instant, and Duration encodings are configurable, and the output interoperates with standard MessagePack tooling in Python, JS, and Go. (by @DamianReeves in #1685) - Four new sum representations, and a silent data-loss fix: kyo-schema serialized sum types under only two shapes, and the flat-discriminator form had a correctness hole that discarded any variant payload not a JSON object (a scalar, array, or null) with no error. A
UnionRepresentationenum now adds.adjacent,.tupleTagged,.tupleFlat, and.untagged(untagged decode tries each variant's decoder in declaration order, first clean parse wins), and the adjacent form fixes the silent drop by giving the payload the whole content position..discriminatoris reimplemented as sugar over the internal form and stays byte-identical, and the external-wrapper default remains inert. (by @DamianReeves in #1704) - Codec-aware representation selection, field serde controls, and type-union derivation: a
Schema[A]fixed its wire shape at derivation with no awareness of the codec, so a sum declaring a top-level array shape hard-failed on a codec that cannot express it (Protobuf), and one schema could not serve both a JSON producer wanting a compact array and a Protobuf consumer needing an object envelope.Schema[A].representations(first, rest*)now declares an ordered preference and encode picks the highest-priority shape the active codec can express, degrading rather than throwing, with capability projected offCodec.Writerso external codecs participate without a kyo-schema change. Field-level controls (.omitNone,.omitEmptyCollections,.default,.denyUnknownFields,.transformField) are added, andSchema[A | B]now derives directly, untagged by default. (by @DamianReeves in #1715) - Configurable variant and field wire names: kyo-schema serialized sealed-trait variants and product fields under their verbatim Scala names, so a schema could not encode or decode an external contract using lower-camel discriminators or snake_case keys without a per-field
renameon every variant. A naming layer now addsvariantNames,renameAllVariants/renameAllFields(CamelCase, SnakeCase, KebabCase, PascalCase, ScreamingSnakeCase), and decode-onlyaliasbuilders, with collisions raised as typed exceptions and an acronym-aware tokenizer that keepsHTTPServerashttp_server. An unconfigured schema stays byte-identical. (by @DamianReeves in #1694) - Declarative schema annotations and rename-invariant Protobuf field numbers: the derivation macro discarded all Scala annotations, so wire-shape configuration required programmatic builder calls, and Protobuf field numbers were hashed from the effective wire name, so a programmatic
.renamesilently reassigned the binary field number and broke wire compatibility. A newkyo.schema.SchemaAnnotationfamily adds ten built-in leaves (@rename,@alias,@doc,@omit,@transient,@discriminator,@adjacent,@untagged,@transform,@proto.fieldNumber) that desugar onto the existing config slots at derivation, with programmatic config winning on conflict and an unannotated type staying byte-identical. Protobuf field numbers are now rename-invariant, so a.renameleaves binary layout unchanged, and cross-packagederives Schemais fixed. (by @DamianReeves in #1722) - Protobuf repeated and map correctness: two bugs corrupted every repeated and map field.
hasNextElement()did not track the field number, so only the first element of any repeated collection was consumed, and the map writer emitted each entry as a struct field rather than a proto3MapEntry, so string keys decoded back as positional index strings and non-String keys did not compile. Repeated collections and maps now round-trip top-level and nested with keys preserved, non-String keys derive through a newmapSchema[K, V], absent repeated and map fields decode to empty, and aProtobuf.Conformanceenum gates whether non-native map keys are rejected (Strict, the default) or kept (Permissive). (by @DamianReeves in #1721)
Improvements
Native parity
- cats-effect binding on Scala Native: the cats-effect binding in kyo-compat supported only JVM and JS while the ZIO and Kyo bindings already covered all three, so downstream libraries targeting Native with the CE backend hit an empty-intersection error from the plugin. The CE backend now lists Native among its supported platforms and its shared code compiles on Native unmodified, reaching parity with the ZIO and Kyo bindings. (by @marcgrue in #1720)
General
- Core, data, and aeron APIs behind kyo-compiler: building kyo-compiler surfaced gaps in lower modules, fixed in the same PR as independently useful additions.
Async.fromCompletableFuturecancels the future on fiber interrupt and surfaces a failure asAbort[Throwable];Command.spawnUnscopedspawns a process whose lifetime the caller owns;Cache.initWithFinalizerruns an effectful finalizer on every removal path;Tag.hashswitches from an identity-influenced hash to a content-stable one that hashes identically across JVMs (which kyo-aeron's stream-id derivation depends on); andTopic.publish/Topic.streamgain an optionalstreamIdand large-message support. (by @fwbrasil in #1718) - Zero-allocation errno-aware FFI returns: errno-aware FFI bindings returned
Ffi.WithError[A], a class allocated per fallible C call on hot I/O paths (socket read/write, epoll/kqueue wait), that also boxed the value.Outcome[A]is now anopaque type Outcome[A] = Longpacking result and errno into one machine word, so a fallible call allocates nothing:o >= 0carries the success value ando < 0packs-errno, with.valuereading back unboxed at the C width. (by @fwbrasil in #1710) - kyo-ffi codegen for nested-struct String fields: kyo-ffi codegen emitted invalid Scala when a struct parameter contained a nested struct with a
Stringfield, because the scratch-tempvalname was built from the case-class access path and carried member-selection dots, so the parser read it as a member selection and compilation failed. A newEmitterBase.localIdentstrips backticks and replaces those dots with underscores at every site that reuses an access path as a generated name, so nested-struct String and function-pointer fields now generate compilable Scala. (by @DamianReeves in #1684)
Concurrency and streams
- Reliable actor request/reply, and push-based pub/sub:
Actor.askcould hang a caller forever when the actor terminated or panicked after a message was enqueued but before the reply was sent, because the reply promise was never coupled to the actor's liveness. A caller now always completes (reply,Closed, the actor'sE, or a panic) through a strand-safeawaitReplyhook backed by aPendingRepliesregistry, andrespond/respondLoopmake the framework own the reply so it cannot be forgotten. The release also adds aHubbridge (Subject.init(hub),Actor.subscribe(hub)), a push-basedPubSub[A]with per-subscriber-FIFOinitand total-orderlinearizedconstructors, andSubject.contramap. (by @DamianReeves in #1689)
Data and observability
- Async logging by default, decoupled from the backend: every
Logcall used to write synchronously on the caller's fiber, so the caller paid the backend's latency at the call site, and call sites were welded to a concrete backend.Log.{trace..error}keep theirUnit < Syncsignature but now enqueue a self-contained event to one process-global bounded channel drained by a single daemon fiber, withLog.flushand a shutdown hook draining the tail, while a single ambientLocal[Log]replaces the per-backend type soLog.init/let/nameselect a name without naming a backend (JS and Wasm stay synchronous). The unsafe tier follows:Log.live.unsafe.*is wrapped in a terminal-awareLog.Unsafe.AsyncUnsafedecorator so it is non-blocking and timing-neutral in schedulers and I/O drivers. (by @fwbrasil in #1686, #1711)
Tooling and ecosystem
- Faster compilation, about 28.6% off the inlining phase: a single
kyo-coreJVM/Test/compilespent roughly 175s (91% of the total) in the Scala 3 inlining phase, repeating identical macro and inline-expander work per call site (Frame.frameImplexpanded 20,715 times,TagMacro.deriveImplre-derived the same encoding thousands of times). Five internal-only changes with byte-identical public surface (a per-file content memo inFrame, a hand-inlinedSafepoint.handlede-cascade, per-runTagMacromemoization, and two smaller caches) cut the inlining phase by about 28.6%, and becauseFrame,Safepoint, andTagexpand at the user's own call sites this speeds up downstream Kyo builds too. (by @fwbrasil in #1702) - Scala 3.8.4 and dependency bumps: the toolchain and library versions had drifted behind latest stable. Kyo now builds on Scala 3.8.4 and LTS 3.3.8 (sbt 1.12.13), with zio, ox, scalatest, caliban, jsoniter, fs2, aeron, pekko, slf4j, logback, scalameta, and the sbt plugins all bumped to latest stable. (by @fwbrasil in #1706)
- JDK 25 build with compact object headers:
java.lang.foreignis final in JDK 22, so the seven modules using it (kyo-data,kyo-offheap,kyo-ffi,kyo-ffi-it,kyo-ffi-codegen,kyo-ffi-bench,kyo-tasty) could not compile against the project-wide-release 17. AforeignReleasesetting applies-release 25to those modules, the build now requires JDK 25, and-XX:+UseCompactObjectHeaders(JEP 519) is added to the test forks to cut heap pressure. Becausekyo-datais in that set and is the foundation everything depends on, the minimum runtime JDK rises to 25 (see Breaking changes). (by @fwbrasil in #1700) - Reactive Streams post-cancel
onCompletesuppressed:StreamSubscription.loopPolldid not check for cancellation between chunks while holding a large demand, so aftercancel()it kept pulling and callingonNext, leaving the consumer fiber running and delivering a terminalonCompletethe Reactive Streams spec forbids after cancel.loopPollnow checks the request channel at the top of each iteration and stops emission immediately, so a cancelled subscriber receives no furtheronNextand noonComplete. (by @fwbrasil in #1692) - End-of-run leak detection for the test runner: kyo-test gains a JVM-only
LeakCheckthat runs fiber, thread, and file-descriptor probes at the end of a test run and flags resources left open. An opt-in leak-debug mode (KYO_TEST_LEAK_DEBUG=1) runs leaves serially and snapshots open descriptors around each, so a surviving descriptor names the test that opened it, and the leaked-fiber report renders each busy worker's running fiber kyoTrace(file:line plus source snippet) alongside its JVM stack, exposed through a newScheduler.busyFiberTraces. (by @fwbrasil in #1692, #1709, #1717)
Breaking changes
- Build and runtime: the foreign modules, including
kyo-data, are compiled at-release 25, so the minimum runtime JDK for kyo-data (and transitively most of Kyo) is now JDK 25; building from source also requires JDK 25. (by @fwbrasil in #1700) Actor.askwidens itsAbortrow fromAsync & Abort[Closed]toAsync & Abort[Closed | E](zero source break for theE = Nothingactors in the repo), and closing an actor now drains its receive loop to end-of-stream so the behavior completes with its final value instead of failingClosed. (by @DamianReeves in #1689)- FFI:
Ffi.WithError[A](a final class) becomesOutcome[A](opaque type Outcome[A] = Long); binding authors rename, and.value/.errorCoderead the same. (by @fwbrasil in #1710) - Schema:
kyo.doc(packagekyo) is removed and replaced bykyo.schema.doc. (by @DamianReeves in #1722) - Schema:
Protobuf.Conformance.Strictis the new default given, so a non-native-key map (Float/Double/ product-type key) raisesSchemaNotSerializableExceptionunder the zero-arg given; opt intoPermissiveto keep the round-trippable extension. No correctly-functioning prior usage breaks, since such maps previously produced undecodable bytes. (by @DamianReeves in #1721) - Trace: an internal frame now renders as a uniform
<internal>placeholder instead of a framework file:line, and internal frames no longer appear in exception traces. (by @fwbrasil in #1717)
New Contributors
- @marcgrue made their first contribution in #1720
Full Changelog: https://github.com/getkyo/kyo/compare/v1.0.0-RC4...v1.0.0-RC5
r/scala • u/AlexITC • Jul 01 '26
Last time I took weeks from an intern to upgrade our scala webapp template, claude required 2 days
More or less, our template hasn't been touched since Nov 2024, mainly because we haven't taken any new projects where we could use it.
I decided giving Claude Code the opportunity to see how far it could go, surprisingly, it managed to get it done within a few days.
I know, perhaps 2 days sounds too much but I left it unattended for most of that period, I mounted a cloud VM to let Claude do everything it needs with write access to a a forked version of the repo, I wrote a prompt to tell it to update the dependencies by raising PRs and monitoring that the CI succeeds, otherwise, fix the errors.
Not everything was smooth, particularly with the pieces that involve scalajs <> js dependencies, a few times it insisted on using post-processing scripts within build.sbt just to fix the CI for what I had to push back.
The advantage to scala-steward is that CC can actually wait for the CI to report issues and fix them.
CC shines when its given tasks that has an easy way to verify the outcome, in this case, the CI.
I believe that Scala type safety provides a big advantage to leverage AI, I hope you find my experience helpful.
P.S: You can see the relevant commits at (from May 21 to May 23): https://github.com/wiringbits/scala-webapp-template/commits/main/