Since I just stood up the `cassandra-ecosystem` repo from CEP-63, the 
`cassandra-utils` topic came to mind (and came up again). Next steps could look 
like:
 1. *Initialize:* Create the `cassandra-utils` repo (initially with zero 
consumers).
 2. *Iterate:* Port selected code from trunk to the new repo, refine the shape, 
and add a separate trunk build path to exercise it.   • *Dependency Strategy:* 
I suggest depending on HEAD of a branch for daily builds to allow 
"auto-updates," then pinning a specific SHA for formal releases. *@Mick*, is 
this legally kosher if one vote covers both the Cassandra release and a pinned 
dependency from another in-foundation project?
   • *Alternative:* We could use SNAPSHOTs and a two-phase release process 
(Vote Utils → Release → Vote Cassandra), similar to the current 
analytics/sidecar discussion.
 3. *Cutover:* Once agreed, switch the default trunk build/CI flow to the 
`cassandra-utils` path.
 4. *Expand:* Continue factoring things out from core Cassandra where it makes 
sense, and start identifying and decoupling duplicated code from other projects 
(analytics, sidecar, drivers, etc.) into `cassandra-utils`.
*Integration Strategy:*
A simple 1:1 branch mapping between Cassandra and `cassandra-utils` as a goal, 
starting with just trunk, seems like the right optimization to me. This 
prioritizes the ease of factoring code out of core Cassandra and deduplicating 
across the ecosystem (accord, cassandra-ecosystem, etc). That'll be a little 
more work for the ecosystem projects to absorb but the benefit of removing 
duplicated code should greatly outweigh that.

Under this model, API contracts could be branch-specific. We could break 
contracts between major versions (e.g., 7.0 to 8.0) provided the primary 
consumer (Cassandra) is updated. The resulting migration work for other 
consumers should be a manageable tax, especially with LLM-assisted workflows, 
so if we wanted to prioritize flexibility on core DB work (which is the highest 
friction / hardest place to get changes in right now) I think that makes sense.

Did I stray too much above David or does this seem viable? Should we take this 
to a CEP? I'd be happy to take that on (having just done CEP-63) since this is 
pretty similar territory.


On Thu, Jun 11, 2026, at 5:41 PM, David Capwell wrote:
> So here is my current thinking
> 
> 1) we fork and have 0 consumers.  This gives us time to make sure the repo is 
> good and we can do releases (so non-cassandra can consume)
> 2) trunk (and only trunk) takes a dependency on cassandra-utils.  This 
> implies 7.0 is the first release we would have with this dependency
> 
> Now, moving forward in time we will have the following situation
> 
> 7.0, 8.0, 9.0, 10.0 (4 maintained releases)
> 
> Since this is a new library that is published this means that the surface 
> area of every API is a *new* public API, so as such *must* follow our rules 
> on breaking changes; needs to be deprecated in a X.0.0 release and can be 
> removed in X+1.0.0, but breaking changes are discouraged and if maintaining 
> compatibility isn’t a massive burden we must maintain.
> 
> Given this my “bigger” concern is the JDK version changes.  JDK releases a 
> long term version every 2 years, and our current average for releases is 
> around 2 years as well… we have had issues keeping up with the JDK version 
> (something we have agreed to try to get better out in your release thread)… 
> so that implies the following to me (rough estimates):
> 
> 7.0 = JDK 29
> 8.0 = JDK 31
> 9.0 = JDK 35
> 10.0 = JDK 39
> 
> Given all this state, this is what I assume should happen
> 
> 1) we have release branches just like C* today, 0.1 for the first release, 
> 0.2 for the next, etc.
> 2) if a bug is found and a breaking change isn’t needed to fix it, we have a 
> patch release.  No Backport
> 
> Assuming we are not making breaking changes, *and* the lib is JDK 29, then 
> 7/8/9/10 can all use the same SHA or release version.  To me we only need to 
> get into the branch maintenance issues if we make breaking changes, so this 
> should be strongly discouraged as it drastically increases the maintenance 
> complexity.  
> 
>> On Jun 11, 2026, at 8:16 AM, Josh McKenzie <[email protected]> wrote:
>> 
>>> What do you mean by this?  A "branch of tools per GA branch” I don’t follow.
>> So if we have the following on C* as GA branches:
>> - cassandra-4.1
>> - cassandra-5.0
>> - cassandra-6.0
>> 
>> We'd have branches on the tools project for:
>> - cassandra-4.1
>> - cassandra-5.0
>> - cassandra-6.0
>> 
>> i.e. we mirror the C* upstream branching strategy and maintain compatibility 
>> between HEAD on both repos. That way we can make changes that are C*-version 
>> specific if needed w/out having to modernize the integration of tooling 
>> w/older C* branches.
>> 
>> If tooling for older branches is unlikely to change, then it seems like the 
>> following might be optimal:
>>  1. new repo
>>  2. branch strategy matching our primary consumer (C*)
>>    1. Backport changes selectively to older branches as needed
>>  3. embed the tooling as a submodule in C*
>> That a distillation of what you're thinking David? Seems reasonable to me.
>> 
>> On Mon, Jun 8, 2026, at 6:24 PM, David Capwell wrote:
>>>> but that introduces the inverse problem where you'd have to make a change 
>>>> across N branches on the shared library if you have a patch that 
>>>> introduces testing that hits all our GA C* and need to backport that 
>>>> functionality instead of changing it in one place.
>>> 
>>> In the case I was talking about its the Property, Gen, and Gens classes, 
>>> and not cluster level tests (similar to python dtest); so don’t think that 
>>> would happen?
>>> 
>>> 
>>>>  • Do we expect the shared functionality in this lib would change 
>>>> frequently in ways that would impact multiple branches, or do we think it 
>>>> would be mostly stable for older branches and mutate more frequently on 
>>>> trunk?
>>> 
>>> I went through our mailing list to see where this has been brought up and a 
>>> common set brought up are "executors/futures/collections/concurrency 
>>> utilities”.  These cases I feel should be the same, that new features are 
>>> for trunk and we don’t really need to back port to older branches unless 
>>> there are bug fixes (in which case we bump the version).  So I work with 
>>> the assumption that back port to older branches isn’t that likely.  Bug 
>>> fixes might need a version bump but should be backwards compatible, new 
>>> features should also not break the public API.
>>> 
>>> One advantage of being a separate and versioned dependency is its easier to 
>>> track when the API is broken, in tree makes this more painful.
>>> 
>>> Now, going through the history of this topic there is a group of things 
>>> that I don’t think make sense to fork, and its stuff like AbstractType / 
>>> Index / IAuthentorictor, etc… plugin authors want a way to handle building 
>>> their plugins without Cassandra-all and these APIs are structurally 
>>> cassandra related.  The stuff I propose extracting out of the code base are 
>>> generic and unaware of cassandra as a project.
>>> 
>>>>  • If the latter (mostly stable, trunk only changes) then having a branch 
>>>> of tools per GA branch would be optimal
>>> What do you mean by this?  A "branch of tools per GA branch” I don’t follow.
>>> 
>>>> From a workflow perspective, a shared library factored out to its own repo 
>>>> and embedded into C* branches as a submodule has some attractive 
>>>> properties either way. It gives you "best of both worlds" (or 
>>>> least-worst-option) by allowing you to work on things seamlessly as though 
>>>> they were one project but keep the branching strategies of the tooling and 
>>>> the dependents decoupled. Even if we only had 1 branch of the test tooling 
>>>> that all C* versions depended on, having it separate and embedded as a 
>>>> submodule should give us the same devx ergonomics while preserving the 
>>>> option to customize per C* branch fairly easily.
>>> 
>>> Yep!  While working on accord I never needed 2 different IDEs open, one for 
>>> accord and one for cassandra; I was able to make changes as if it was a 
>>> single project and the only complexity for development was making sure CI 
>>> knew about my accord branch (we have a script in tree for that) and merge 
>>> is 3 steps rather than 1 (merge accord, update cassandra to point to latest 
>>> accord, merge cassandra).
>>> 
>>> Sub modules do have down sides we are currently living with (as you have 
>>> seen working with CI) and I do hope its been mostly seamless for people… 
>>> 
>>> I can also see us trying out a hybrid model… trunk is submodule but once we 
>>> fork a major branch we switch to release jars instead; we get the trunk 
>>> level velocity and loose all the pain points of submodules when working in 
>>> a release branch.
>>> 
>>>> On Jun 8, 2026, at 7:25 AM, Josh McKenzie <[email protected]> wrote:
>>>> 
>>>>> One other motivation for forking is that we can fix issues one time 
>>>>> rather than have to fix in 5 branches that have slightly different 
>>>>> versions of our libraries. 
>>>> The pain on this one is real. Spit-balling, but I wonder if there'd be a 
>>>> way to sustainably have all GA branches depend on this code from trunk and 
>>>> we use testing and validation to ensure the code on trunk stays compatible 
>>>> with older releases.
>>>> 
>>>> There's a lot of complexity there since we'd need CI updated to run that 
>>>> subset of tooling tests across all GA branches before a commit (i.e. trunk 
>>>> only changes would then potentially impact all GA branches), but maybe 
>>>> that actually wouldn't be so bad if we just had a new pipeline that pulled 
>>>> and built all GA branches from HEAD and ran through the tooling test 
>>>> suites against those releases. That, and it'd only really be in scope if 
>>>> you were making changes to that tooling. That said, it would seem pretty 
>>>> weird for 5.0 to need to check out code from the trunk branch to build and 
>>>> run tests against though... =/
>>>> 
>>>>> My primary need is for test utilities so my focus is there.
>>>> Hm. Yeah, the more I think through this, having a versioned set of test 
>>>> utilities in trunk for instance would definitely feel like "crossing the 
>>>> streams" (i.e. PropertyTestingBase4.0, PropertyTestingBase4.1, etc). Big 
>>>> separation of concerns / scope failure if people working on a trunk branch 
>>>> in C* are having to think about other branches and API breakage with them 
>>>> (moreso than we already have to w/mixed version upgrades etc.)
>>>> 
>>>> Having things like that in a separate repo where we could cut iterate on 
>>>> things to update for a single branch would alleviate that immediate 
>>>> versioning / mismatch context leak, but that introduces the inverse 
>>>> problem where you'd have to make a change across N branches on the shared 
>>>> library if you have a patch that introduces testing that hits all our GA 
>>>> C* and need to backport that functionality instead of changing it in one 
>>>> place.
>>>> 
>>>> Blech.
>>>> 
>>>> So as I was drafting the above, my thinking has distilled down to the 
>>>> following as being important to have a shared mental model on:
>>>>  • Do we expect the shared functionality in this lib would change 
>>>> frequently in ways that would impact multiple branches, or do we think it 
>>>> would be mostly stable for older branches and mutate more frequently on 
>>>> trunk?
>>>>    • If the former (multi-branch impacting blast radius, we keep older GA 
>>>> branches in sync / compatible with test harness changes), a single golden 
>>>> copy of the shared code that each branch shares would minimize toil
>>>>    • If the latter (mostly stable, trunk only changes) then having a 
>>>> branch of tools per GA branch would be optimal
>>>> 
>>>> From a workflow perspective, a shared library factored out to its own repo 
>>>> and embedded into C* branches as a submodule has some attractive 
>>>> properties either way. It gives you "best of both worlds" (or 
>>>> least-worst-option) by allowing you to work on things seamlessly as though 
>>>> they were one project but keep the branching strategies of the tooling and 
>>>> the dependents decoupled. Even if we only had 1 branch of the test tooling 
>>>> that all C* versions depended on, having it separate and embedded as a 
>>>> submodule should give us the same devx ergonomics while preserving the 
>>>> option to customize per C* branch fairly easily.
>>>> 
>>>> On Fri, Jun 5, 2026, at 9:25 AM, David Capwell wrote:
>>>>> One other motivation for forking is that we can fix issues one time 
>>>>> rather than have to fix in 5 branches that have slightly different 
>>>>> versions of our libraries. A recent example is CASSANDRA-21216 which was 
>>>>> a bug fix for btree.  
>>>>> 
>>>>> One of the other reasons brought up in the past is that many libraries 
>>>>> are needed by accord but accord can’t depend on Cassandra else we have a 
>>>>> cyclical dependency, so forking off let’s accord use our libraries.  For 
>>>>> the time being accord had to fork many libraries in accord to make 
>>>>> progress; this is a common issue right now.
>>>>> 
>>>>> 
>>>>> 
>>>>> Sent from my iPhone
>>>>> 
>>>>>> On Jun 3, 2026, at 1:45 PM, Josh McKenzie <[email protected]> wrote:
>>>>>> 
>>>>>>> delays this effort for years as we need time to get people on board and 
>>>>>>> used to gradle before we flip that switch. 
>>>>>> Oof. I'm way more optimistic on this one; if we can get a PR that has 
>>>>>> ant targets as dumb wrappers that instead call gradle targets (i.e. all 
>>>>>> workflows and local scripting Just Work), I don't see why we couldn't 
>>>>>> merge that as soon as we ironed out kinks.
>>>>>> 
>>>>>> Is there anyone that's broadly against that approach? Or did I just 
>>>>>> misunderstand the other thread / JIRA you'd created David?
>>>>>> 
>>>>>> On Wed, Jun 3, 2026, at 1:21 PM, David Capwell wrote:
>>>>>>> Fair point but one thing to point out, if this work depends on gradle 
>>>>>>> that delays this effort for years as we need time to get people on 
>>>>>>> board and used to gradle before we flip that switch.  So leaving in 
>>>>>>> tree means we have to hand roll all that logic in ant. 
>>>>>>> 
>>>>>>> Sent from my iPhone
>>>>>>> 
>>>>>>>> On Jun 3, 2026, at 12:33 PM, Jon Haddad <[email protected]> 
>>>>>>>> wrote:
>>>>>>>> 
>>>>>>>> Josh is right.  Gradle subprojects could allow this without dealing 
>>>>>>>> with separate repo.  I've done this before and am about to again for 
>>>>>>>> some stuff I maintain.  I spent a long time agonozing over this for my 
>>>>>>>> other projects and found it works exceptionally well, especially bc 
>>>>>>>> you frequently develop things that are tightly coupled.  
>>>>>>>> 
>>>>>>>> Juggling repos sucks, this solves it (imo) perfectly.
>>>>>>>> 
>>>>>>>> Jon
>>>>>>>> 
>>>>>>>> On Tue, Jun 2, 2026 at 1:18 PM Josh McKenzie <[email protected]> 
>>>>>>>> wrote:
>>>>>>>>> __
>>>>>>>>>> Is there a reason not to use a folder in the current repo that 
>>>>>>>>>> becomes its own jar?  It can even be published separately if we like?
>>>>>>>>> 
>>>>>>>>>> Mostly to decouple from Cassandra release.
>>>>>>>>> I *think* we could just have that .jar release on its own cadence 
>>>>>>>>> independently of the parent C* project.
>>>>>>>>> 
>>>>>>>>> Some of us have talked about taking this same approach to making some 
>>>>>>>>> code from C* available to the ecosystem (think I/O .jar that has 
>>>>>>>>> SSTable read/write, CommitLog read/write, etc). This feels like a 
>>>>>>>>> very similarly shaped thing.
>>>>>>>>> 
>>>>>>>>> I assume w/a modern build / publish / etc system we'd be able to 
>>>>>>>>> publish a release that represents a strict subset of the parent 
>>>>>>>>> project out of the repo right?
>>>>>>>>> 
>>>>>>>>> On Mon, Jun 1, 2026, at 8:18 PM, David Capwell wrote:
>>>>>>>>>> Mostly to decouple from Cassandra release.  If there is a feature 
>>>>>>>>>> added does it have to wait for the next major release of Cassandra 
>>>>>>>>>> so others can consume?  Even if we can get to yearly releases that’s 
>>>>>>>>>> still a long wait.
>>>>>>>>>> 
>>>>>>>>>> For example Alex and I have been talking about proper fuzz testing, 
>>>>>>>>>> so best case is a year before 3rd parties could use.
>>>>>>>>>> 
>>>>>>>>>> Sent from my iPhone
>>>>>>>>>> 
>>>>>>>>>>> On Jun 1, 2026, at 4:32 PM, Jeremiah Jordan <[email protected]> 
>>>>>>>>>>> wrote:
>>>>>>>>>>> 
>>>>>>>>>>> Does it need to be a separate repo? Is there a reason not to use a 
>>>>>>>>>>> folder in the current repo that becomes its own jar?  It can even 
>>>>>>>>>>> be published separately if we like?
>>>>>>>>>>> 
>>>>>>>>>>> -Jeremiah
>>>>>>>>>>> 
>>>>>>>>>>> On Jun 1, 2026 at 10:00:15 AM, David Capwell <[email protected]> 
>>>>>>>>>>> wrote:
>>>>>>>>>>>> Hi all,
>>>>>>>>>>>> 
>>>>>>>>>>>> We've discussed pulling utilities out of trunk before. I'd like to 
>>>>>>>>>>>> actually start.  My primary need is for test utilities so my focus 
>>>>>>>>>>>> is there.
>>>>>>>>>>>> 
>>>>>>>>>>>> This isn't just my need. Sidecar wants property/stateful tests but 
>>>>>>>>>>>> can't use ours without a published jar.
>>>>>>>>>>>> 
>>>>>>>>>>>> Proposed approach:
>>>>>>>>>>>> 
>>>>>>>>>>>> 1. Define scope — start with property/stateful test utilities
>>>>>>>>>>>> 2. Set up the repo and release independently of Cassandra
>>>>>>>>>>>> 3. ...
>>>>>>>>>>>> 4. Cassandra depends on the library
>>>>>>>>>>>> 
>>>>>>>>>>>> I'd focus on the fork first, before making Cassandra depend on it 
>>>>>>>>>>>> — keeps our builds simple and gives the lib room to stabilize. We 
>>>>>>>>>>>> can sort out the dependency question later (wait on releases, or 
>>>>>>>>>>>> use submodules?).
>>>>>>>>>>>> 
>>>>>>>>>>>> Happy to drive this if there's interest.
>>>>>>>>>>>> 
>>>>>>>>>>>> Sent from my iPhone
>>>>>>>>> 
>>>>>> 
>>>> 
>> 

Reply via email to