Explain the auto-generated binding name convention (<name>-in-0/-out-0) and how you map bindings to broker destinations and consumer groups.
answer
- <name>-in-<index>, <name>-out-<index>
- index only grows with multi in/out
- destination maps logical->physical topic
- .group = competing consumers + durable
- no group = broadcast to every instance
basics
~10 sSCSt names bindings <functionName>-in-<index> and <functionName>-out-<index>. You map each to a real topic/queue with spring.cloud.stream.bindings.<binding>.destination, and set a consumer group with .group so instances share the load.
solid answer
~40 sEach activated function gets logical bindings derived from its bean name plus direction and index: `<name>-in-0` for the first input and `<name>-out-0` for the first output. The index increments for multi-input/multi-output functions. These are logical names; you connect them to physical broker destinations with `spring.cloud.stream.bindings.<binding>.destination=<topic>`. For competing-consumer semantics you add `.group=<groupId>`, which makes all instances in that group share a partitioned/queue subscription rather than each getting every message. Without a group, each instance is an anonymous consumer and receives all messages (pub-sub). Producer-side and consumer-side extra settings live under `.producer.*` and `.consumer.*`. Understanding the naming matters because the property keys must exactly match the generated binding name, including the `-0` suffix.
code
java · 22 lines// application.yml
// spring:
// cloud:
// function:
// definition: uppercase
// stream:
// bindings:
// uppercase-in-0:
// destination: raw-words
// group: word-service # competing consumers, durable
// consumer:
// concurrency: 3
// max-attempts: 3
// uppercase-out-0:
// destination: processed-words
// producer:
// partition-count: 4
@Bean
public Function<String, String> uppercase() {
return String::toUpperCase;
}go deeper
Recall the -in-0/-out-0 pattern and that destination maps it to a topic.
Explain index semantics, consumer groups (broadcast vs competing), and durability.
Discuss consumer/producer sub-properties, binder-specific overrides, and decoupling names via spring.cloud.stream.function.bindings alias.
Reason about scaling/partitioning topology, durable-group operational implications, and multi-destination fan-in trade-offs.
**Binding = the logical pipe** between your function and the broker. SCSt generates a name for every input and output of every activated function using a strict convention: ``` <functionName>-in-<index> // inputs <functionName>-out-<index> // outputs ``` - `functionName` is the bean name (or the composed name — see composition). - `in`/`out` is the direction relative to your app. - `<index>` starts at `0`. It is `0` for the common single-input/single-output case, and increments only for functions with multiple inputs or outputs (e.g. `Function<Tuple2<Flux<A>,Flux<B>>, ...>` yields `-in-0` and `-in-1`). **Mapping to a physical destination.** The generated name is logical; you bind it to a broker topic/queue: ``` spring.cloud.stream.bindings.uppercase-in-0.destination=raw-words spring.cloud.stream.bindings.uppercase-out-0.destination=processed-words ``` If you omit `.destination`, SCSt defaults the destination to the binding name itself — convenient in demos, but you normally set it explicitly so the topic name isn't coupled to your bean name. **Consumer groups.** By default a consumer binding subscribes anonymously — every application instance receives every message (broadcast/pub-sub). To get **competing consumers** (each message handled by exactly one instance, enabling horizontal scaling), set a group: ``` spring.cloud.stream.bindings.uppercase-in-0.group=word-service ``` On Kafka this maps to a Kafka consumer group; on RabbitMQ it creates a durable shared queue. Named groups also make the subscription **durable**, so messages published while the app is down are retained. **Consumer / producer sub-settings.** Common tuning goes under nested prefixes: ``` spring.cloud.stream.bindings.uppercase-in-0.consumer.concurrency=3 spring.cloud.stream.bindings.uppercase-in-0.consumer.max-attempts=3 spring.cloud.stream.bindings.uppercase-out-0.producer.partition-count=4 ``` Binder-specific properties (Kafka/Rabbit) live under `spring.cloud.stream.kafka.bindings.<binding>...` etc. **Descriptive binding names.** If you dislike the derived name, you can decouple it: set `spring.cloud.stream.function.bindings.uppercase-in-0=input` to alias it to `input`, then configure `spring.cloud.stream.bindings.input.destination=...`. Useful when migrating old configs that referenced `input`/`output`. **Gotchas.** - The property key must match the binding name *exactly*, including `-0`. A typo like `uppercase-in` (missing index) silently fails to apply and the binding uses defaults. - The index refers to the position in the function's type signature, not to how many topics you listen on. - `destination` can be a comma-separated list on the consumer side to fan-in multiple topics into one binding.
- What happens if two instances of the app run without a consumer group configured?Both instances subscribe anonymously and each receives every message (pub-sub broadcast), so the message is processed twice. Adding `.group` makes them a single competing-consumer group where each message is handled once.
- How would you make one input binding listen to multiple topics?Set the destination to a comma-separated list, e.g. `spring.cloud.stream.bindings.uppercase-in-0.destination=t1,t2`. The binding fans those topics into the same function input.
saying these in an interview costs you the question
- Writing the key as <name>-in without the -0 index and expecting it to apply
- Assuming each instance gets each message exactly once even without a group
- Thinking the index counts topics rather than positions in the function signature