Hi all, Thanks for the feedback. I've updated the KIP to reflect the overload-based approach we discussed:
- A new functional interface `ValueJoinerWithMultipleKeys<K1, K2, V1, V2, VR>` that exposes both the mapped join key and the stream record key (using the name Matthias suggested, to avoid the easy-to-miss collision with `ValueJoinerWithKey`). - Four new overloads of `KStream#join` / `leftJoin` (the GlobalKTable variants) taking the new joiner. - The four existing `ValueJoinerWithKey`-based overloads are deprecated, with Javadoc that explicitly calls out that `readOnlyKey` there is the stream key, not the join key, and points users at the new method. - The original `joinByMappedKey` / `leftJoinByMappedKey` proposal is now listed under Rejected Alternatives. Updated KIP URL: https://cwiki.apache.org/confluence/display/KAFKA/KIP-1340%3A+Expose+Both+Mapped+Key+and+Stream+Key+in+Streams-GlobalKTable+Joins Happy to hear further feedback. Best regards, Lucy Liu On Mon, Jun 22, 2026 at 1:13 PM Matthias J. Sax <[email protected]> wrote: > The only name I could come up with is `ValueJoinerWithMultipleKeys` ? > > > -Matthias > > On 6/12/26 2:47 AM, Alieh Saeedi via dev wrote: > > Thanks Lucy and Matthias. > > > > > > > > > > > > I also lean toward the second approach (the ValueJoinerWithKeys > overload). > > Although the initial approach is an easier fix, the future for each > > approach would be: > > - Under the second approach: one join family — join/leftJoin — with > > different joiner flavors. It's internally consistent and learnable from > > existing knowledge. > > > > - Under the first approach: join for some variants and joinByMappedKey > > for others — a method name that appears nowhere else in the API, > justified > > by an internal detail/nuance (mapped key != record key) > > > > > > Just one thing I'd want to raise: The naming: ValueJoinerWithKeys > (plural) > > is one character different from the existing "ValueJoinerWithKey" > > (singular). Since both live in the same package and appear together in > > autocomplete, this naming similarity is an easy long-term footgun (also > > confusing). Could we consider a less collision-prone name? I don't have a > > great one yet, but I'd raise it now than after it's public. > > > > > > Thanks > > - Alieh > > > > > > On Fri, Jun 12, 2026 at 3:06 AM Matthias J. Sax <[email protected]> > wrote: > > > >> Thanks for digging into the details. > >> > >> What you found matches my understanding. Overall, it's a tricky > >> tradeoff. Personally, I think it's better to keep the more prominent > >> API, ie, KStream#join() clean, so the alternative to add > >> `ValueJoinerWithKeys` (plural) might be the better tradeoff. > >> > >> Would be good to also hear from others about it. > >> > >> > >> -Matthias > >> > >> > >> On 6/4/26 12:44 PM, Lucy Liu via dev wrote: > >>> Hi Matthias, thanks for the feedback! > >>> > >>> MJS1: Yes, compile-time, not runtime. I reworded that. > >>> > >>> MJS2, MJS3, MJS4: > >>> I agree that introducing the new methods will lead to name asymmetry. > If > >> we > >>> add a new join/leftJoin overload taking a new functional interface > rather > >>> than introducing new methods, all stream-globalTable joins could keep > the > >>> same join/leftJoin naming. So I explored the last rejected alternative > >>> further: a new ValueJoinerWithKeys interface `ValueJoinerWithKeys<K1, > K2, > >>> V1, V2, VR>` with `apply(readOnlyKey, streamKey, value1, value2)` > >> exposing > >>> both keys, and overloaded the existing join/leftJoin methods to accept > >> it. > >>> The four ValueJoinerWithKey overloads get @Deprecated as in the > original > >>> plan, but the migration target is now the new overload rather than a > >>> renamed method. The ValueJoiner overloads stay untouched. > >>> For example, the new `join` method would be: > >>> > >>>> <GlobalKey, GlobalValue, VOut> KStream<K, VOut> join(final > >>>> GlobalKTable<GlobalKey, GlobalValue> globalTable, > >>>> final > >>>> KeyValueMapper<? super K, ? super V, ? extends GlobalKey> keySelector, > >>>> final > >>>> ValueJoinerWithKeys<? super GlobalKey, ? super K, ? super V, ? super > >>>> GlobalValue, ? extends VOut> joiner); > >>> > >>> > >>> I think this could be a better solution because the overload works > >> cleanly, > >>> and the joiner allowing both keys offers greater flexibility. > >>> This is some draft code changes this approach would introduce: > >>> > >> > https://urldefense.com/v3/__https://github.com/apache/kafka/pull/22477__;!!Ayb5sqE7!t-Pgojx5hrlsNZCev0a6uksclbJfRMZotq56k4WSPVrACGz_vECOVEhjiAQqr7bMkJEQqbWHHCtUCY-1$ > >>> > >>> Happy to learn what others think about this approach. If this approach > is > >>> indeed better, I will update the KIP. > >>> > >>> Best regards, > >>> Lucy Liu > >>> > >>> > >>> > >>> On Wed, Jun 3, 2026 at 4:43 PM Matthias J. Sax <[email protected]> > wrote: > >>> > >>>> Thanks for the KIP Lucy. > >>>> > >>>> Overall, it seems to be a non-controversial proposal, to solve the > issue > >>>> with new overloads. > >>>> > >>>> > >>>> > >>>> MJS1: The KIP says: > >>>> > >>>>> The discrepancy is not surfaced at runtime > >>>> > >>>> What this paragraph describe is a compile time type check, right? Not > a > >>>> runtime check? > >>>> > >>>> > >>>> > >>>> MJS2: It seems you propose to replace only the 4 methods which take > >>>> `ValueJoinerWithKey` argument. While this is the smallest change we > >>>> could make, I am wondering if it introduced some name inconsistencies? > >>>> So even if technically not necessary, I am wondering if we would get > >>>> better UX, if we would also deprecate the 4 method taking > `ValueJoiner`? > >>>> This way, all method which are doing the same thing, ie > >>>> stream-globalTable join have the same name. > >>>> > >>>> > >>>> > >>>> MJS3: About naming the new methods. I guess both `joinOnMappedKey` and > >>>> `joinByMappedKey` would work. But I am wondering if > >>>> `foreignKeyJoin()`would be good names, too? Or maybe > >>>> `globalKTableJoin()`? Just putting forward some alternatives to spark > >>>> some thoughts. Naming is always hard. Curious to hear what others > think. > >>>> > >>>> > >>>> > >>>> MJS4: About the last rejected alternative. If my assessment is right, > it > >>>> would have the advantage that we could add new overloads called > >>>> `join()`, and thus we would get better method naming overall, and my > >>>> point MJS2 from above would become void? I does have the disadvantage > >>>> that we need a new interface, but given the naming question, I am > >>>> wondering if it would provide an overall better tradeoff? -- Again, > >>>> curious to hear what others think. > >>>> > >>>> > >>>> -Matthias > >>>> > >>>> > >>>> > >>>> On 5/27/26 10:17 PM, Lucy Liu via dev wrote: > >>>>> Hi Bill, > >>>>> > >>>>> Thanks for the suggestions! I have made some changes accordingly. > >>>>> BB1: I changed the 4 added methods to use `by` instead of `on`. > >>>>> BB2: For each deprecated method, an additional warning comment will > be > >>>>> added, stressing that the `readOnlyKey` is the stream key and might > not > >>>> be > >>>>> behaving as intended. > >>>>> > >>>>> Best, > >>>>> Lucy > >>>>> > >>>>> On Wed, May 27, 2026 at 4:07 PM Bill Bejeck <[email protected]> > >> wrote: > >>>>> > >>>>>> Hi Lucy, > >>>>>> > >>>>>> Thanks for the KIP! This is a very much needed update to Kafka > >> Streams. > >>>>>> Overall the KIP looks good. > >>>>>> > >>>>>> BB1. I have one nit comment with regards to the name. What would > you > >>>> think > >>>>>> about `joinByMappedKey / leftJoinByMappedKey` instead? > >>>>>> BB2. Since the error condition will continue to exist until we > remove > >>>> the > >>>>>> deprecated methods, maybe we could add one line to the Javadoc > >>>> explicitly > >>>>>> stating that readOnlyKey is currently the stream key, not the mapped > >>>> join > >>>>>> key. > >>>>>> > >>>>>> Thanks, > >>>>>> Bill > >>>>>> > >>>>>> On Tue, May 26, 2026 at 1:19 PM Lucy Liu via dev < > >> [email protected]> > >>>>>> wrote: > >>>>>> > >>>>>>> Hi everyone, > >>>>>>> > >>>>>>> Gentle ping on this thread. Looking forward to feedback on the KIP! > >>>>>>> > >>>>>>> Best, > >>>>>>> Lucy Liu > >>>>>>> > >>>>>>> On Fri, May 15, 2026 at 4:19 PM Lucy Liu <[email protected]> > >> wrote: > >>>>>>> > >>>>>>>> Hello everyone, > >>>>>>>> > >>>>>>>> I would like to start a discussion on KIP-1340 Pass Join Key to > >>>>>>>> `ValueJoinerWithKey` in Streams-GlobalKTable Joins > >>>>>>>> < > >>>>>>>> > >>>>>>> > >>>>>> > >>>> > >> > https://urldefense.com/v3/__https://cwiki.apache.org/confluence/display/KAFKA/KIP-1340*3A*Pass*Join*Key*to**A60ValueJoinerWithKey*60*in*Streams-GlobalKTable*Joins__;JSsrKysrJSUrKys!!Ayb5sqE7!sMsc7OEJtzyBJn3kfDmAjAi8gklV-8hDbb2Oiwk_NV0RC8giJPWimU7sX4jc4Niu_29yjxAv1souD4H5kUY$ > >>>>>>>>> > >>>>>>>> > >>>>>>>> This proposal aims to introduce joinOnMappedKey and > >>>>>> leftJoinOnMappedKey, > >>>>>>>> new KStream methods that pass the mapped join key (the result of > the > >>>>>>>> user-supplied KeyValueMapper) into ValueJoinerWithKey for > >>>>>>>> stream-globalTable joins. The existing join/leftJoin overloads > pass > >>>> the > >>>>>>>> stream record's key into the joiner instead, contradicting > KIP-149's > >>>>>>>> contract that readOnlyKey is the join key and silently producing > >> wrong > >>>>>>>> values if a joiner intends to read the real join key. The existing > >>>>>>>> overloads will be deprecated and removed in a future major > release. > >>>>>>>> > >>>>>>>> Best regards, > >>>>>>>> Lucy Liu > >>>>>>>> > >>>>>>> > >>>>>> > >>>>> > >>>> > >>>> > >>> > >> > >> > > > >
