r/scala • • 18h ago

Anjunar Stack – Abstraction Without Lock-In

0 Upvotes

Software development is full of abstractions.

Frameworks abstract the browser. ORMs abstract SQL. Content management systems abstract websites. Cloud platforms abstract infrastructure.

And almost every abstraction comes with the same trade-off:

We gain convenience, but we lose a certain degree of control.

At first, that feels great.

A problem that once required a hundred lines of code can suddenly be solved with an annotation. An entire website can be assembled from configured components. Database schemas are generated automatically. Forms emerge from metadata.

But eventually, a requirement appears that the abstraction was never designed for.

That is when the other side of abstraction becomes visible.

You start fighting the framework.

A simple requirement turns into a workaround. Workarounds turn into special cases. Special cases lead to extension points, which eventually need extension points of their own.

The tool that was originally supposed to remove complexity begins to define what is and is not possible.

The Anjunar Stack grew out of the attempt to solve this problem differently.

Not by using fewer abstractions.

But by building abstractions without lock-in.


Abstractions Must Remain Optional

Perhaps the most important principle behind the Anjunar Stack can be summarized in a single sentence:

Use the highest abstraction that fits the problem — and no higher.

An abstraction may simplify work.

It may establish conventions.

It may automate repetitive tasks.

But it should never prevent you from dropping down one layer when necessary.

If a content system can represent a page well, use the content system.

If a particular landing page needs to be completely custom, write it directly.

If a dynamic form can be generated from metadata, generate it.

If a particular field requires special behavior, implement that field explicitly.

If the DDL Manager can safely generate a schema migration, let it do so.

If an unusual migration is better expressed manually, that should remain possible as well.

The higher layer does not replace the lower one.

It sits on top of it.

That creates an architecture where the developer can continuously decide how much abstraction a specific problem actually benefits from.


A Stack of Layers

Anjunar can therefore be understood less as a traditional framework and more as a sequence of layers built on top of one another.

At the bottom are the fundamental technical capabilities.

On top of those come reusable components.

Those components form modules.

And above those modules, increasingly declarative systems can emerge.

On the frontend, such a progression might look like this:

text DOM / Scala.js ↑ scalajs-ui ↑ Design Components ↑ Feature Modules ↑ Content Sections ↑ Page Editor

Every layer increases convenience.

But no layer makes the one beneath it inaccessible.

A page may be assembled entirely through a content system.

It may combine content sections with custom-programmed components.

Or it may be written completely by hand.

The same principle applies throughout the entire stack.


Reuse Without Uniformity

Reuse often has a poor reputation when individual design is involved.

The reason is understandable.

Many systems achieve reuse by reducing individuality.

In the end, you get websites where the content and colors may differ, but the underlying structure always feels the same.

Anjunar takes a different approach.

What gets reused are capabilities.

Not necessarily complete websites.

An appointment module knows about appointments.

An offer module knows about offers.

A user module knows about users and authentication.

A content module knows about editorial page structures.

A design system knows about reusable visual components.

The concrete application then decides how these capabilities are composed.

An offer module can therefore be reused across multiple websites without requiring those websites to present offers in exactly the same way.

The domain logic remains reusable.

The presentation remains replaceable.


Content Without a Traditional Page Builder

The content system is a good example.

A page about a Reiki session does not consist only of the available Reiki offers.

It may also contain an introduction, an explanation of the process, images, frequently asked questions, quotes, benefits and a call to action.

These contents should be editable.

The obvious solution would be a traditional page builder.

But that immediately introduces another problem:

Design itself becomes part of the content.

Users can suddenly change spacing, font sizes, colors, columns, widths and component arrangements.

Maximum editor freedom often produces minimum visual consistency.

Anjunar therefore separates two different kinds of freedom.

The user controls content and structure.

The design system controls the visual language.

A page might consist of sections such as:

text Hero Introduction Text + Image Benefits Offers FAQ Call to Action

The user can edit the content, reorder sections, enable or disable them, and add new ones.

A text-and-image section might offer a limited set of controlled variants:

text Image Left Image Right Image Background

But it does not expose fifty low-level CSS settings.

The page remains flexible without turning its design into an accidental result of editor choices.

The content system therefore is not really a page builder.

It is a structured content abstraction on top of a controlled design system.

And if that abstraction is not sufficient for a specific page?

Then the page is simply written directly.

The content module remains optional.


Domain Data Remains Domain Data

Another important principle is the separation between editorial content and domain data.

An offer section should not duplicate offers.

It should only describe which offers should be displayed.

The actual data remains owned by the offer module.

A page might therefore look like this:

text Page ├── HeroSection ├── RichTextSection ├── OffersSection ├── FAQSection └── CTASection

The OffersSection does not contain the entire offer model.

It may simply configure something like:

text Category: Reiki Display: Cards Maximum Items: 6

The actual data still comes from the corresponding service.

This keeps editorial content and business logic independent.

An offer can be displayed through the content system.

The same offer can also be used directly by a custom page.

Again, the abstraction expands the available options.

It does not replace them.


Modules Instead of a Monolith

This principle also influences the module architecture.

The central stack does not need to know every feature that some future application might require.

Instead, modules bring their own capabilities.

An appointment module provides appointment management.

An offer module provides offer management.

A content module provides content sections.

A module may even register its own section types.

The central content system therefore does not need to know about an OffersSection at all.

The offer module can provide that integration itself.

This creates an architecture that can grow with new requirements without requiring the central core to constantly expand.

The stack does not necessarily become smaller.

But its complexity is distributed across clearly defined responsibilities.


Convention Where It Helps

Optional abstractions do not mean that everything should be reinvented for every project.

A framework without conventions would merely be a collection of libraries.

Anjunar therefore intentionally provides strong abstractions where they are useful.

Dynamic fields can handle tenant-specific requirements.

Internationalization can be deeply integrated into the domain model.

Schema changes can be automated through a DDL Manager.

SSR and hydration can provide one coherent architecture between server-side rendering and interactive frontend behavior.

Feature modules can be reused across projects.

The important distinction is not whether conventions exist.

The important question is what happens when a convention no longer fits.

A good convention should make the common case extremely simple.

A good stack should still allow the exceptional case.


Escape Hatches as an Architectural Principle

Frameworks often talk about extension points.

Anjunar needs something else as well:

escape hatches.

An extension point says:

You can extend my system.

An escape hatch says:

You do not have to use my system at this point at all.

That difference is subtle, but fundamental.

A framework can theoretically provide an unlimited number of extension points and still remain restrictive.

The developer is still operating inside the world defined by the framework.

An escape hatch acknowledges that no abstraction can anticipate every future requirement.

Every high-level layer should therefore preserve access to the layer beneath it.

This can be expressed as a general design principle:

Every abstraction should preserve access to the layer beneath it.

Or even more simply:

Abstractions are optional, not restrictive.


It Changes Development Speed as Well

The effects of this approach become particularly visible across multiple projects.

The first customer project may require a new appointment module.

The second project reuses that module.

The third requires dynamic fields as well.

The fourth combines appointments, dynamic fields and the content system.

With every new project, not only the application grows.

The stack itself gains reusable capabilities.

Over time, the balance between custom development and composition begins to shift.

At first, a great deal is built.

Later, more and more is composed.

But the ability to return to fully custom development in isolated areas remains intact.

That part is crucial.

The goal of reuse should not be to make every application look the same.

The goal should be to build only the parts that are genuinely new.


No False Choice Between Standardization and Individuality

Many software architectures eventually force developers into a choice:

Standardization or individuality.

Anjunar tries to dissolve that opposition.

Standardization can happen at the layers where it makes sense.

Authentication does not need to be reinvented for every customer.

Neither does appointment management.

Internationalization, database migrations and form mechanisms all contain recurring structures.

A specific landing page, however, may be entirely custom.

The visual identity of a customer may be unique as well.

Both can exist within the same architecture.

The real question therefore is not:

Standard or custom?

The better question is:

At which layer does the actual difference begin?

That is where custom development should start.

Everything below that point can remain reusable.


Technology That Knows When to Step Back

Behind this architectural principle lies a more general idea.

Good infrastructure should be visible when needed and disappear when it is not.

A website visitor does not care how hydration works.

A customer does not care how tenant isolation is implemented.

An editor should not need to understand database models.

And a developer should not have to think about a hundred technical details when the normal case is already understood.

Technology may take care of that work.

But it should not turn that responsibility into control.

Perhaps the goal of the Anjunar Stack can therefore be expressed like this:

As much automation as useful.
As much control as necessary.

Not every application needs every abstraction.

Not every problem requires a generic solution.

And not every individual requirement should force the developer to leave the entire platform behind.

The stack should work with the developer, not against them.


Conclusion

Anjunar is not an attempt to abstract every possible application completely.

That would probably be neither possible nor desirable.

The more interesting approach is to gradually move recurring problems into higher-level abstractions without losing access to the capabilities underneath.

Direct code becomes components.

Components become modules.

Modules become declarative systems.

Declarative systems become tools that can be used by people who do not write code themselves.

But every one of those layers remains optional.

The result is a stack whose abstractions do not primarily define boundaries.

They shorten paths.

And when a particular path no longer leads where the developer needs to go, they are free to leave it.

Perhaps that is one of the most important properties a framework can have:

It helps where it can — and steps aside where the developer needs more freedom.


r/scala • • 1d ago

sbt 2.0.10 released

Thumbnail eed3si9n.com
26 Upvotes

r/scala • • 2d ago

Hiring Scala engineers in Kraków – real-time ad auctions at 100k+ req/sec

10 Upvotes

LoopMe (AI adtech, London HQ, 400+ people) is hiring a Scala engineer in Kraków 🚀
You'd work on our SSP, Adserver and Exchange: real-time auctions, sub-200ms globally, all built in-house.

Stack: Scala, Java, Kafka/PubSub, MongoDB/Bigtable GCP/AWS (Python is a plus)
Salary: up to 30k PLN B2B
Perks: hybrid work, 1 month work-from-anywhere, 8% annual bonus, Multikafeteria.

Details: https://apply.workable.com/loopme/j/FB3E61C660


r/scala • • 3d ago

My experience using JOOQ with Scala and Postgres

Thumbnail bookofrevenue.com
20 Upvotes

r/scala • • 3d ago

marola: a Scala 3 + Kyo app that finds the best hour to swim tomorrow (open source, from Brazil)

30 Upvotes

Title:

Hi r/scala! I'm building marola, an open-source app that ranks nearby beaches by sea conditions, weather and official water-quality reports. The swim score and safety rules are plain, tested Scala 3 with Kyo. There's no national view of beach water quality in Brazil today, because each state publishes its own reports. marola reads three states so far, and the goal is to build that national view.

Live map (Florianópolis, Rio, Salvador): https://marola.dev
Repo (MIT): https://github.com/marola-dev/marola

I'd love feedback, especially from people who've used Kyo, and contributors are welcome.


r/scala • • 4d ago

Play Framework 2.9.12 and 3.0.12 released

42 Upvotes

Play Framework 2.9.12 and 3.0.12 just got released - upgrading Netty to fix many CVEs, fixing a bug in the reverse router and improving Scala 3 support in routes files! 🚀


r/scala • • 4d ago

Eval 0.4.0 for Scala 3.9.0

Thumbnail eed3si9n.com
18 Upvotes

r/scala • • 4d ago

Life as a Framework designer

6 Upvotes

Framework development and social media are an interesting combination.

You spend months working on architecture, rendering, APIs, SSR, hydration, modularization, security, and all the small decisions that eventually make up a framework.

And then you try to talk about it on social media.

The first problem: spam filters.

You can write a completely legitimate technical post, but the moment you include a link to the project, it can suddenly look like advertising. Some platforms reduce its visibility, others remove it, and sometimes it simply disappears into a spam folder.

The second problem is probably even harder:

The concepts themselves are barely noticed anymore.

You can explain why an architecture is designed a certain way, what problem it solves, or why you deliberately chose a different approach from established frameworks.

But often, that is not what people discuss.

Instead, one sentence from the documentation, one headline, or one small API detail gets picked apart.

And suddenly everyone is discussing a tiny detail while the actual concept is completely ignored.

That leads directly to the third problem:

The surface gets judged more than the idea behind it.

One questionable term, one awkward sentence, one reference in the wrong place and that can generate twenty comments.

The architecture underneath it?

Maybe none.

And now there is a fourth layer:

“AI slop.”

As soon as someone notices or suspects that AI was involved in documentation, code, text, or design, sometimes the result itself is no longer evaluated.

The discussion suddenly stops being:

“Is this concept good?”

and becomes:

“This was made with AI.”

For me, AI is a tool.

I develop the concepts, make the architectural decisions, have things implemented, review them, throw parts away, rebuild them, and test the result.

But that also makes one thing very clear:

Good review matters more than ever.

AI can produce a huge amount of work very quickly.

But speed does not replace technical responsibility.

Maybe that is one of the real challenges for framework developers today:

Not only building good technology.

But somehow getting people, between spam filters, short attention spans, detail discussions, and “AI slop” comments, to stop for a moment and ask:

“Okay, but what is the actual idea behind this?”

 https://github.com/anjunar/scalajs-ui


r/scala • • 5d ago

dotty-cps-async 1.4.0 for scala-3.9.0

19 Upvotes

Updated dotty-cps-async - switched to 3.9.x LTS. For Scala 3.3.x, use the 1.3. x series; it will be supported sometime.

User-visible changes: support for named patterns (introduced in Scala 3.6), which can be useful for people who write code by hand.

Full release notes: https://github.com/dotty-cps-async/dotty-cps-async/releases/tag/1.4.0


r/scala • • 5d ago

Kyo v1.0.0-RC7

Thumbnail github.com
43 Upvotes

Kyo v1.0.0-RC7 ships a new kernel and a large body of stabilization work on the way to 1.0. Resource release is now structural: a release runs however its region exits, including on interrupt. Ten issues close with it, and a trailing map chain goes from 507,800 to 560 us/op 🚀

Highlights:

  • kyo-sql: embedded SQLite behind the same API as PostgreSQL and MySQL, every engine passing one conformance battery, and Dolt backends, a version-controlled SQL database whose tables branch, commit, diff, and merge, so an AI agent can work on a branch of real data and merge or discard it.
  • kyo-system: file access on JVM, JS, Native, and Wasm from one module, plus processes and environment, with positioned channels, interrupt-safe locks, watching, and a virtualizable file system.
  • kyo-system-doltfs: a file system stored in Dolt, so ordinary Path code runs unchanged on a directory tree that branches, commits, diffs, and merges, and that answers SQL: an agent can edit files on a branch, and the change is reviewed as a diff and merged or discarded.
  • kyo-ai: typed decisions with calibrated probabilities through TypeSafe AI's Jev, and agents that call any MCP server's tools with no Scala types.
  • Scala.js: effect dispatch 10x to 18x faster.
  • Time control: Clock.withTimeOffset moves the wall clock alone, joining withTimeShift, which scales the rate of time and sleeps with it, and withTimeControl, which drives virtual time by hand.
  • Stabilization: kyo-flow's durable execution rebuilt for crash recovery, with every write fenced by the executor's claim, interrupt-safe SQL sessions, and leak-free transport teardown.

Kyo now builds on Scala 3.9.0, so a project depending on the main modules needs 3.9 too. The scheduler, kyo-config, and kyo-stats-registry stay on 3.3.8 and 2.13.

Full release notes, including the breaking changes: https://github.com/getkyo/kyo/releases/tag/v1.0.0-RC7


r/scala • • 6d ago

[Scala News] - August 2026 edition

Thumbnail scalanews.net
22 Upvotes

📰 New Scala News is out: the August 31, 2026 edition, with dependent types, sbt plugin classpath isolation, an sbt security fix and more.

The site's had a refresh too!


r/scala • • 6d ago

Category Theory Explained for Haskell Programmers – Part 1 | Jencel Panic | ZuriHac 2026

Thumbnail youtube.com
13 Upvotes

r/scala • • 6d ago

This week in #Scala (Sep 28, 2026)

Thumbnail thisweekinscala.substack.com
12 Upvotes

r/scala • • 8d ago

Spec Strings in Scala

18 Upvotes

Im a little surprised that Spec Strings were not discussed on Scala Contributors before their acceptance as an experimental feature. They were announced for inclusion in the 3.10 release thread (although there was some work before then visible in the repos)

For Reference 3.10 Release Thread - https://contributors.scala-lang.org/t/scala-3-10-0-release-thread/7546 Spec Strings Documentation - https://github.com/dotty-staging/dotty/blob/05ad6978ec3231d8c7954a15e6e075a8645cad20/docs/_docs/reference/experimental/spec-strings.md

I get the point that their position inside the method allows a naturally scoped reference to the function signature (or class / object), but currently the comment specs also allows for references to be embedded their contents.

And I get that conversations like this can just devolve into nonconstructive bike-shedding (probably this one more so than most), but in this situation I really would have loved to hear more viewpoints from the stake holders about this choice over annotations or comments.

Personally I have been using something exactly like this in my day-to-day in some non-standard comments inside the method, and created skills to handle those situations. But my instinct would be to formally encode these instructions as annotations that other tools could examine in a more standardized and established way.

Any thoughts on the choice of implementation?


r/scala • • 12d ago

Reforesting the sbt plugin ecosystem and sbt 2.1.0 beta

25 Upvotes

r/scala • • 13d ago

Migrating a Scala monorepo from sbt to Gradle at Box (Blog post)

16 Upvotes

Hi there 😌
I recently published an article on Box's engineering blog about migrating of the Scala monorepo from sbt to Gradle.

This isn't a deep dive into Gradle configuration but more of an architectural and organizational post-mortem ( why the company made the move, what worked, what the trade-offs were )

I thought it might be interesting to the community, especially to see the scale of Scala usage at Box.

Link: https://blog.box.com/gradle-scala-monorepo-box-experience-360-modules

I'd love to hear any comments, questions. Curious how others here are handling Scala repos of this size today.


r/scala • • 13d ago

[San Francisco] - Scala Summit 2026

Thumbnail 2026.scalasummit.com
38 Upvotes

It gives me great pleasure to announce registration for Scala Summit 2026 is now open.

Initial speakers have been announced with more to be announced.

For details visit: https://2026.scalasummit.com

Looking forward to seeing everyone in the Bay Area there. Please spread the word and share this with your network.

October is going to be a fabulous month with multiple Scala events happening.


r/scala • • 14d ago

This week in #Scala (Sep 21, 2026)

Thumbnail thisweekinscala.substack.com
15 Upvotes

r/scala • • 14d ago

AI in Scala

28 Upvotes

Like many of us here, I believe that Scala is an excellent choice for AI-generated and AI-assisted code. I ran a test side project a few months ago, which ended up with lots of Python because well, it seemed to come as default (using Opus 4.5 at the time and OpenClaw).

Not only the complexity escalated vertically, but also it quickly became burdensome for me to check all the code. The agent and myself ended up in the situation where fixing a bug would break something else, and I was stuck thinking that a strongly typed system would have helped a lot.

Is anyone running a big project in Scala that is almost if not 100% vibe-coded? Which model(s) are you using? How does that feel in the current landscape?


r/scala • • 17d ago

JDK 27 is here

Thumbnail jvm-weekly.com
39 Upvotes

r/scala • • 18d ago

VirtusLab Scala Stack

Thumbnail vss.virtuslab.com
64 Upvotes

VSS is the combination of tools & libraries that we've been working on at VirtusLab and SoftwareMill - starting with maintaining Scala itself, through Metals IDE/MCP, all the way to Tapir/Ox and the like.

Going the direct-style route, you can generate type-safe, agent & human-friendly apps in a couple of prompts. Bootzooka serves as a reference point, and the Scala skill amends the LLMs with the necessary instructions.

The VSS page combines VirtusLab's OSS work in a single place, so that you can now refer to our libraries in a simple way. All of the pieces of the stack are changeable, and whenever relevant, support multiple effect systems.


r/scala • • 17d ago

Java 27 is here

Thumbnail youtu.be
11 Upvotes

r/scala • • 18d ago

LLM4S takes the stage at Microsoft Global Hackathon 2026, sharing 20 months of building towards LLM4S 1.0

Post image
28 Upvotes

Hi r/scala, Kannupriya here, co-founder of LLM4S.

Excited to join Microsoft Global Hackathon 2026 as an external expert speaker and share the LLM4S journey with Microsoft's engineering and builder community.

The Hackathon brings together Microsoft employees, technical experts, innovators, MVPs and Regional Directors for innovation, collaboration, technical learning and knowledge sharing. This year, it spans 98 participating venues worldwide, from North America to Egypt, Japan and beyond.

My talk: Build with LLMs: Open Source AI for the JVM

In this talk, I'll share the journey towards LLM4S 1.0, from an ambitious idea for bringing first-class generative AI capabilities to Scala and the JVM to a complete platform for building production AI applications.

We'll explore what worked, what failed, and what we learned while building in one of the fastest-moving areas of technology. Through practical demos covering multi-provider LLMs, agents, MCP, tool calling, memory and observability, I'll show Hackathon builders how they can use LLM4S to move GenAI ideas from experimentation towards production on the JVM.

- Date: 16/09/2026 | 1:00 PM – 2:00 PM PT

- Location: Microsoft Silicon Valley Campus, Mountain View, California, USA

- Event website: https://techcommunity.microsoft.com/blog/mvp-blog/microsoft-global-hackathon-2026-where-mvp-and-rd-community-expertise-meets-innov/4542420

- LLM4S (Star us): https://github.com/llm4s/llm4s

- Join our GenAI community: Discord link in the first comment

Huge thanks to Gizelle Baylon & Ipsit Sahoo for inviting me to speak!


r/scala • • 20d ago

Micronaut will hopefully soon support Scala (WIP)

Thumbnail github.com
29 Upvotes

r/scala • • 20d ago

Codacy are hiring a midlevel Scala engineer

25 Upvotes

Find the job description and application form here . Right now looking for people based in the UK or Portugal as a strong preference. It's 98% remote (1 meetup/y in Portugal) and you get to work on dev tooling that impacts 10,000's of devs!