Good day. After brainstorming, thoughtful consideration, and other similar efforts, we decided that the only feasible option is to remove the Graph interface from the public API and, hopefully, eventually from internal as well. That will encourage users to use queries for most, if not all, data manipulations.
As for the next step, we will propose our view of the TX management API. On Mon, Nov 24, 2025 at 2:06 PM Andrii Lomakin <[email protected]> wrote: > I apologize for sending another message to this thread. > > Our primary motivation for limiting access to the Structure API > immediately is straightforward: changing a public API is a major > undertaking. By limiting it now, we will force ourselves to design a > universal, Turing-complete API from the ground up that supports both > embedded and remote deployments. > > This approach will enable our users to start with a small embedded > database and scale up to a large cloud cluster without requiring > significant application refactoring. > > Best regards, > Andrii Lomakin > > On Mon, Nov 24, 2025 at 1:55 PM Andrii Lomakin < > [email protected]> wrote: > >> Just to clarify, that is part of our GraphTraversalDSL >> https://github.com/JetBrains/youtrackdb/blob/develop/core/src/main/java/com/jetbrains/youtrackdb/api/gremlin/YTDBGraphTraversalSourceDSL.java#L49 >> . >> >> >I think this idea begs to be explored >> >> We will start experimenting with it then. We have thought about it for a >> long time, so you can base your changes on what we have made. >> >> On Mon, Nov 24, 2025 at 1:51 PM Andrii Lomakin < >> [email protected]> wrote: >> >>> Hi Stephen. >>> Thank you for the feedback. Regarding transactions, after I wrote the >>> letter, I am inclined to think that the approach using GraphTraversal that >>> we currently use is closer to what I want to see in the TinkerPop process >>> API than the steps designed to control TXs. >>> >>> BTW, we use the autoExecute approach a lot :-) >>> >>> /// Start a new transaction if it is not yet started and executes >>>> passed in code in it. >>>> /// >>>> /// If a transaction is already started, executes passed in code in >>>> it. In case of exception, >>>> /// rolls back the transaction and commits the changes if the >>>> transaction was started by this >>>> /// method. >>>> public <X extends Exception> void executeInTx( >>>> @Nonnull FailableConsumer<YTDBGraphTraversalSource, X> code) >>>> throws X { >>>> var tx = tx(); >>>> YTDBTransaction.executeInTX(code, (YTDBTransaction) tx); >>>> } >>> >>> >>> /// Start a new transaction if it is not yet started and executes >>>> passed in code in it. >>>> /// >>>> /// If a transaction is already started, executes passed in code in >>>> it. In case of exception, >>>> /// rolls back the transaction and commits the changes if the >>>> transaction was started by this >>>> /// method. >>>> /// >>>> /// Unlike {@link #executeInTx(FailableConsumer)} also iterates over >>>> the returned >>>> /// [YTDBGraphTraversal] triggering its execution. >>>> public <X extends Exception> void autoExecuteInTx( >>>> @Nonnull FailableFunction<YTDBGraphTraversalSource, >>>> YTDBGraphTraversal<?, ?>, X> code) >>>> throws X { >>>> var tx = tx(); >>>> YTDBTransaction.executeInTX(code, (YTDBTransaction) tx); >>>> } >>> >>> >>> /// Start a new transaction if it is not yet started and executes >>>> passed in code in it and then >>>> /// returns the result of the code execution. >>>> /// >>>> /// If a transaction is already started, executes passed in code in >>>> it. In case of exception, >>>> /// rolls back the transaction and commits the changes if the >>>> transaction was started by this >>>> /// method. >>>> public <X extends Exception, R> R computeInTx( >>>> @Nonnull FailableFunction<YTDBGraphTraversalSource, R, X> code) >>>> throws X { >>>> var tx = tx(); >>>> return YTDBTransaction.computeInTx(code, (YTDBTransaction) tx); >>>> } >>> >>> >>> On Mon, Nov 24, 2025 at 1:44 PM Stephen Mallette <[email protected]> >>> wrote: >>> >>>> Generally speaking, I think this idea begs to be explored but I also >>>> think >>>> that it's a change of extraordinary size that will need a lot of thought >>>> and planning to be sure it is done properly. I think initial efforts >>>> with >>>> that plan are already underway with 3.8.0 where it introduced the >>>> notion of >>>> StepContract interfaces and "step placeholders" which should allow >>>> providers to more easily provide their own implementations. In this >>>> way, a >>>> provider would be implementing at a Gremlin level rather than at that >>>> Structure API level. So, that's a starting point to allow for any of >>>> this >>>> to happen. I don't recall past discussions about what happens to Element >>>> interfaces, but I sense they would end up being read-only as you >>>> described. >>>> I suppose they would stay interfaces and there would be a few concrete >>>> TinkerPop implementations that we'd offer for providers to convert to >>>> when >>>> implementing steps. Remote providers might skip all that together and >>>> just >>>> write directly to GraphSON or GraphBinary. >>>> >>>> I don't know if transactions should explicitly be implemented as a >>>> traditional Step or not. They don't behave like steps in my mind, in >>>> that I >>>> don't see how they chain. Maybe it's more like a terminal step or a >>>> special step series like io().read()/write(). I think the first work to >>>> be >>>> taken around this big topic is to try to build consensus for what >>>> transactions look like, both as a part of the Gremlin language and the >>>> HTTP >>>> API. I know Ken has been thinking about the Transaction API for 4.x, >>>> but no >>>> formal proposal has been raised yet that I can recall. >>>> >>>> I will add that while I feel the Transaction API is a must-have for 4.x, >>>> I'm not sure that I see removal of the Graph API as a critical item for >>>> that version. If there was consensus on a plan to do so, I think it >>>> would >>>> be best for that to fall into a later body of work where perhaps the >>>> deprecation for the Graph API is in 4.x with removal in 5.x. >>>> >>>> On Sat, Nov 22, 2025 at 8:49 AM Andrii Lomakin via dev < >>>> [email protected]> wrote: >>>> >>>> > Dear like-minded colleagues, >>>> > >>>> > Sorry for the stream of ideas, but I wanted to share my thoughts on >>>> API >>>> > dual support. >>>> > >>>> > I believe the dual support of two API types—structured and process—is >>>> > counterproductive because it prevents the creation of truly >>>> > platform-independent distributions. >>>> > When an application development team begins to rely on the structured >>>> API, >>>> > they become limited to a minimal number of vendors who support >>>> embedded >>>> > deployments. >>>> > >>>> > Furthermore, I agree with Stephen Mallette that it is more >>>> straightforward >>>> > and more idiomatic for a provider to implement a few basic steps that >>>> > operate on database records than to implement the more demanding >>>> interface >>>> > of a Graph instance. >>>> > >>>> > In practice, this suggests the following changes: >>>> > >>>> > 1. Remove the Graph interface as a public API. >>>> > 2. Make the Element, Vertex, and Edge concepts read-only. >>>> > 3. Add steps to control transactions uniformly at the GraphTraversal >>>> level >>>> > to unify management. >>>> > >>>> > Regarding transaction management, the current implementation appears >>>> to be >>>> > an ununified side feature, especially considering the disparate >>>> lifecycles >>>> > between embedded and remote deployments. Introducing steps that >>>> control the >>>> > transaction lifecycle would resolve this issue. >>>> > >>>> > What do you think about these points? >>>> > We will consider implementing those items on our side in the short >>>> term. >>>> > >>>> > Best regards, >>>> > Andrii Lomakin >>>> > YouTrackDB development lead. >>>> > >>>> >>> -- Andrii Lomakin YouTrackDB development lead
