I tend to think APIs, SPIs, and any other stable public elements (e.g., public model classes, like PolarisEntity, PolarisPrincipal, Configuration objects, Exceptions) should be treated almost the same. For example, the deprecation process and backward compatibility should be handled similarly. Maybe we should define a broader term, such as "public contract" or "public interface."
Yufei On Mon, Jul 20, 2026 at 9:42 AM EJ Wang <[email protected]> wrote: > Hi Dmitri, > > Following up here since it connects with PR5052, which just merged. > CatalogConfigEndpointContributor landed in runtime/service for now. On that > PR I argued core is too broad and runtime is too Quarkus-specific for it, > and suggested punting the real "where does this go long-term" question to a > separate issue rather than blocking the merge on it. You agreed, merged as > is. I don't see that issue filed yet, so figured this thread works as well > as any. > > A few things weren't fully clear to me in the writeup: > > 1. The API/SPI split hinges on "when multiple alternatives exist", is > that about how many alternatives exist today, or design intent to allow > more later? A plugin point with exactly one default implementation, > built that way on purpose, still reads like an SPI to me even with a > single > implementer. > 2. Same question on the placement rule, you allow the SPI to live inside > X when X is already guaranteed to be a dependency of its own > implementations, curious what governs it when that's true for some > implementers and not others. > 3. And on point 4, the compile-error safety net assumes downstream > rebuilds against new releases before it matters, not every consumer > does. > Probably its own thread though, I'm thinking of more on the client and > server side (schema versioning on the wire, not something to hash out > here). > > Separately, curious how general the placement rule is meant to be. > Polaris's own dependency graph, every extensions/* implementation already > has to depend on polaris-core, lands on keeping SPIs like PolarisAuthorizer > and PolarisMetaStoreManager inside core rather than split out. > > Is "ideally X-spi per module" the default shape with the in-X case being > rare, or are both equally "ideal" depending on which way the dependency > graph points, no inherent preference either way? > And on GenericTableEndpoints, the thing I raised on the same PR, it's not > an SPI either, nobody implements a wire-format constant. Does your model > have a read on where that kind of thing goes, or is it genuinely outside > what you're describing here? > > One more thing, more analogy than a literal claim, not saying the > REST-serving layer is an SPI. But if you squint at it that way, Quarkus > being today's default impl, a hypothetical Spring binding being another, it > points at a real in-between layer: framework-agnostic REST-serving logic > that isn't quite core and isn't quite runtime either, the same shape as the > GenericTableEndpoints question, just one layer up. Your examples are all > in-process, CDI-selected at runtime, this would be a build-time, > different-deployable choice, a different axis than what you described. Not > asking you to settle whether it's an SPI, more whether that in-between > layer is something your placement thinking has a slot for. > > -ej > > On Mon, Jul 13, 2026 at 5:42 PM Dmitri Bourlatchkov <[email protected]> > wrote: > > > Hi All, > > > > I'm sending this email hoping to confirm alignment of the Polaris > community > > members on SPI development principles in this project. I do not think we > > need strong and formal rules / guidelines as long as the community has > > consensus on the general approach. > > > > Recap: SPI = Service Provider Interface > > > > * What is the difference between API and SPI? > > > > API is meant to be invoked by a client on a library (or service) in order > > to cause the library (service) to perform a certain action. > > > > SPI is meant to be implemented by a library / service plugin in order to > > provide a method for performing certain actions when multiple > alternatives > > exist. > > > > Example from Polaris: > > > > IcebergRestCatalogApiService is an API that represents the IRC spec in > > terms of java classes. > > > > Authenticator is an SPI that defines what Polaris code requires an > > authorization framework to implement. The default impl. > > is DefaultAuthenticator, OPA and Ranger implementation and alternatives > > that can be plugged in via CDI + configuration. > > > > * Where should SPI classes be located normally? > > > > Without considering the legacy code in Polaris, I believe SPI classes > > should be located such that they require minimal depdency leaks into the > > module implementing the SPI. Ideally all SPI classes used by module X > > should be located in a module "X-spi" to convey that they are associated > > with X. > > > > This is not to say that existing code must be refactored immediately to > fit > > these patterns. This is a proposal for future evolution. > > > > If module X can be expected to be a dependency of its SPI > implementations, > > the SPI classes can be placed inside X itself. > > > > * Should SPI classe be in polaris-core? > > > > If polaris-core requires defines a plugin point, the SPI for that can > > certainly be in polaris-core. > > > > BasePersistence is an example of a core SPI. > > > > * Can SPI interfaces have breaking changes from the java language > > perspective? > > > > Yes. Unline API, SPI interfaces define what plugins must implement. not > > what clients rely on. > > > > For example, adding a parameter to an SPI method will cause a compilation > > error downstream, but it's ok. This is a signal to the downstream SPI > > implementation that it is expected to process the new parameter. It is a > > good breakage in the sense that it will inform the downstram > implementation > > and prevent invalid behaviour that might occur as a result of ignoring > the > > new parameter. > > > > In many cases this is not a hard failure downstream. Normally, the > > downstream project will get those compilation errors inside a PR that > > updates its Polaris dependencies. It will not be a deployment time error > > (which is common with service API changes). > > > > Thoughts? > > > > Thanks, > > Dmitri. > > >
