Skip to content

Add proposal documentation for xDS server-side integration#6766

Open
jrhee17 wants to merge 1 commit into
line:mainfrom
jrhee17:proposal/xds-server
Open

Add proposal documentation for xDS server-side integration#6766
jrhee17 wants to merge 1 commit into
line:mainfrom
jrhee17:proposal/xds-server

Conversation

@jrhee17

@jrhee17 jrhee17 commented May 14, 2026

Copy link
Copy Markdown
Contributor

Motivation

Armeria's existing xDS support is client-side only: XdsBootstrap fetches Listener/Route/Cluster/Endpoint resources and feeds them into XdsEndpointGroup for service discovery and load balancing.

Server-side xDS is a different use case. Instead of discovering upstream services, the Armeria server itself becomes an xDS-managed workload. A control plane (Istio, CentralDogma, etc.) pushes configuration that governs how the server accepts connections, negotiates TLS, and enforces policies like RBAC — while the user's services and routing remain entirely under their control.

This PR proposes a design for server-side xDS integration, adding two documents that describe the architecture and public API surface.

@jrhee17 jrhee17 added this to the 1.40.0 milestone May 14, 2026
@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR introduces two design and specification documents that establish the architectural foundation and public API surface for server-side xDS integration in Armeria. The changes define how xDS resources map to Armeria server components, the semantic constraints governing decorator and filter execution, the core APIs for plugin registration and connection management, and the entry point for integrating xDS control plane provisioning.

Changes

Server-Side xDS Design and API Specification

Layer / File(s) Summary
Design Vision and Scope
xds/docs/SERVER_DESIGN.md
Establishes goals (Armeria as xDS-managed workload with user services as final dispatch layer) and non-goals (dynamic ports, xDS routing, non-HCM filters).
Architectural Model and End-to-End Flow
xds/docs/SERVER_DESIGN.md, xds/docs/SERVER_PROPOSAL.md
Defines Envoy-to-Armeria resource mapping (listener→ServerPort, SDS→ServerTlsProvider, http_filters→decorators), filter-chain structure, and composition flow from plugin registration through connection acceptance to request decoration.
Design Constraints and Semantic Choices
xds/docs/SERVER_DESIGN.md
Documents xDS route_config exclusion from dispatch, no per-route filter overrides, xDS decorator lifecycle, decorator reuse per filter chain, per-connection snapshot consistency, decorator ordering (xDS RBAC/authn before user decorators), and connection-time filter-chain binding.
Public API Contracts
xds/docs/SERVER_PROPOSAL.md
Introduces ServerPlugin, ConnectionAcceptor, ConnectionContext, ServerTlsProvider interfaces; modifies ServerBuilder (add plugin/acceptor/TLS provider), ServiceRequestContext (add connectionContext()), and Server (install/reconfigure/stop plugin lifecycle).
XDS Server Plugin Entry Point
xds/docs/SERVER_PROPOSAL.md
Defines XdsServerPlugin constructor overloads and install responsibilities (port, connection acceptor, ServerTlsProvider, root decorator); describes internal ServerSnapshotWatcher role.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

A rabbit designs with care and grace,
xDS filters in their proper place—
Decorators dance, semantics bind,
Connections flow with ordered mind.
From specs to APIs, the blueprint's clear,
Let server-side harmony appear! 🐰✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add proposal documentation for xDS server-side integration' accurately and concisely summarizes the main change: introducing design documentation for server-side xDS support in Armeria.
Description check ✅ Passed The description clearly explains the motivation for server-side xDS integration, contrasts it with existing client-side xDS support, and accurately describes the two documents being added.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (8)
xds/docs/SERVER_PROPOSAL.md (3)

17-34: ⚡ Quick win

Add language specifier to code block.

The fenced code block lacks a language specifier. Adding text will improve readability and fix the markdownlint warning.

📝 Proposed fix
-```
+```text
 Connection arrives
        |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@xds/docs/SERVER_PROPOSAL.md` around lines 17 - 34, The fenced code block in
SERVER_PROPOSAL.md should include a language specifier to satisfy markdownlint
and improve readability; edit the block that documents the flow (containing
ConnectionAcceptor.accept, ConnectionContext, ServerTlsProvider.serverTlsSpec,
ServerTlsSpec, TLS handshake, XdsRootDecorator.serve, and
ServiceRequestContext.connectionContext()) and change the opening fence from ```
to ```text so the diagram is marked as plain text.

10-15: ⚡ Quick win

Add language specifier to code block.

The fenced code block lacks a language specifier. Adding java will improve syntax highlighting and fix the markdownlint warning.

📝 Proposed fix
-```
+```java
 Server.builder()
     .addPlugin(new XdsServerPlugin(bootstrap, "listener", 8080))  -- [ServerPlugin, XdsServerPlugin]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@xds/docs/SERVER_PROPOSAL.md` around lines 10 - 15, Add the missing language
specifier to the fenced code block in SERVER_PROPOSAL.md so markdownlint
highlights it as Java; update the opening fence from ``` to ```java for the
block containing Server.builder(), .addPlugin(new XdsServerPlugin(...)),
.service("/api", myService) and .build() so the snippet (including
XdsServerPlugin and Server.builder) is rendered with Java syntax highlighting.

174-180: Document timeout and failure handling for the blocking install() call.

This design proposal describes install() blocking until the first xDS snapshot is resolved, but lacks documentation on several operational aspects:

  • No timeout is specified for the blocking operation, which could cause server startup to hang indefinitely if the xDS control plane is unreachable
  • No guidance on how deployments should handle control plane unavailability scenarios (retry logic, timeouts, fallback behaviors)
  • No recommendations for health check configuration during the blocking initialization phase

Consider clarifying in the design:

  1. Whether a configurable timeout should be added
  2. How users should handle xDS control plane connectivity issues at startup
  3. Best practices for monitoring and health checks during the blocking phase
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@xds/docs/SERVER_PROPOSAL.md` around lines 174 - 180, The docs lack
operational guidance for the blocking install() call; update SERVER_PROPOSAL.md
near the install() description to specify a configurable timeout (e.g.,
installTimeoutMs) and default behavior, document retry/backoff strategies and
fallback options when the xDS control plane is unavailable (e.g., fail fast vs
continue with cached/default snapshot), and add recommendations for health
checks and startup probes during the blocking phase (e.g., return STARTING vs
UNHEALTHY, expose a non-blocking readiness endpoint). Reference the install()
entry, ConnectionAcceptor behavior, and ServerTlsProvider resolution so readers
know where timeouts/retries apply and how health-check semantics should map
during initialization.
xds/docs/SERVER_DESIGN.md (5)

74-94: ⚡ Quick win

Add language specifier to code block.

The fenced code block lacks a language specifier. Adding text will improve readability and fix the markdownlint warning.

📝 Proposed fix
-```
+```text
 xDS Listener (port 8080)
  ├── FilterChain: mTLS
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@xds/docs/SERVER_DESIGN.md` around lines 74 - 94, The fenced code block
showing the xDS Listener diagram is missing a language specifier; update the
opening fence for that block (the triple backticks before the "xDS Listener
(port 8080)" diagram) to include the language token `text` (i.e., change ``` to
```text) so the markdownlint warning is resolved and the diagram renders with
the correct highlighting/formatting.

72-72: ⚡ Quick win

Fix heading formatting.

Remove extra spaces after the hash to comply with markdown style guidelines.

📝 Proposed fix
-###  Sample listener
+### Sample listener
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@xds/docs/SERVER_DESIGN.md` at line 72, The markdown heading "###  Sample
listener" has an extra space after the hashes; update the heading in
SERVER_DESIGN.md (the "Sample listener" heading) to remove the extra space so it
reads "### Sample listener" to comply with markdown style guidelines.

53-70: ⚡ Quick win

Add language specifier to code block.

The fenced code block lacks a language specifier. Adding text or yaml will improve syntax highlighting and fix the markdownlint warning.

📝 Proposed fix
-```
+```text
 Listener (name: "inbound_0.0.0.0_8080")
  └── FilterChain(s)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@xds/docs/SERVER_DESIGN.md` around lines 53 - 70, Add a language specifier to
the fenced code block that documents the Listener/FilterChain example (the block
starting with ``` and containing "Listener (name: \"inbound_0.0.0.0_8080\")" and
the FilterChain tree) by changing the opening fence to include a language such
as ```text or ```yaml so markdownlint highlighting is enabled; keep the existing
content and closing ``` unchanged.

172-172: ⚡ Quick win

Use American English phrasing.

Replace "In future" with "In the future" for consistency with American English conventions.

📝 Proposed fix
-In future, we could support dynamically binding ports to listeners via wildcard listener
+In the future, we could support dynamically binding ports to listeners via wildcard listener
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@xds/docs/SERVER_DESIGN.md` at line 172, Replace the phrase "In future" with
"In the future" wherever it appears (exact string "In future") in the
SERVER_DESIGN.md content to conform to American English phrasing; look for the
occurrence in the documentation text and update it to "In the future" ensuring
spacing and punctuation remain correct.

149-151: ⚡ Quick win

Add language specifier to code block.

The fenced code block lacks a language specifier. Adding text will improve readability and fix the markdownlint warning.

📝 Proposed fix
-```
+```text
 [xDS RBAC] → [xDS authn] → [user's service decorators] → service
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@xds/docs/SERVER_DESIGN.md` around lines 149 - 151, Add a language specifier
to the fenced code block containing the arrow diagram "[xDS RBAC] → [xDS authn]
→ [user's service decorators] → service" by changing the opening
triple-backticks to include "text" (i.e., ```text) so the block declares its
language and satisfies markdownlint; update the fenced block around that exact
diagram in SERVER_DESIGN.md.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@xds/docs/SERVER_PROPOSAL.md`:
- Around line 99-108: Align the null-handling semantics by making sniHostname()
nullable: change ConnectionContext.sniHostname() to return "@Nullable String"
(instead of empty string) to match alpnProtocols() semantics; update the
interface signature, any javadoc/docs in SERVER_PROPOSAL.md, all implementations
of ConnectionContext (and their constructors/builders) to return null when SNI
is absent, and adjust callers/tests to handle null rather than empty string.
Ensure Attribute: reference sniHostname() and alpnProtocols() in the same style
across the codebase and run tests to catch call sites that assumed an empty
string.

---

Nitpick comments:
In `@xds/docs/SERVER_DESIGN.md`:
- Around line 74-94: The fenced code block showing the xDS Listener diagram is
missing a language specifier; update the opening fence for that block (the
triple backticks before the "xDS Listener (port 8080)" diagram) to include the
language token `text` (i.e., change ``` to ```text) so the markdownlint warning
is resolved and the diagram renders with the correct highlighting/formatting.
- Line 72: The markdown heading "###  Sample listener" has an extra space after
the hashes; update the heading in SERVER_DESIGN.md (the "Sample listener"
heading) to remove the extra space so it reads "### Sample listener" to comply
with markdown style guidelines.
- Around line 53-70: Add a language specifier to the fenced code block that
documents the Listener/FilterChain example (the block starting with ``` and
containing "Listener (name: \"inbound_0.0.0.0_8080\")" and the FilterChain tree)
by changing the opening fence to include a language such as ```text or ```yaml
so markdownlint highlighting is enabled; keep the existing content and closing
``` unchanged.
- Line 172: Replace the phrase "In future" with "In the future" wherever it
appears (exact string "In future") in the SERVER_DESIGN.md content to conform to
American English phrasing; look for the occurrence in the documentation text and
update it to "In the future" ensuring spacing and punctuation remain correct.
- Around line 149-151: Add a language specifier to the fenced code block
containing the arrow diagram "[xDS RBAC] → [xDS authn] → [user's service
decorators] → service" by changing the opening triple-backticks to include
"text" (i.e., ```text) so the block declares its language and satisfies
markdownlint; update the fenced block around that exact diagram in
SERVER_DESIGN.md.

In `@xds/docs/SERVER_PROPOSAL.md`:
- Around line 17-34: The fenced code block in SERVER_PROPOSAL.md should include
a language specifier to satisfy markdownlint and improve readability; edit the
block that documents the flow (containing ConnectionAcceptor.accept,
ConnectionContext, ServerTlsProvider.serverTlsSpec, ServerTlsSpec, TLS
handshake, XdsRootDecorator.serve, and
ServiceRequestContext.connectionContext()) and change the opening fence from ```
to ```text so the diagram is marked as plain text.
- Around line 10-15: Add the missing language specifier to the fenced code block
in SERVER_PROPOSAL.md so markdownlint highlights it as Java; update the opening
fence from ``` to ```java for the block containing Server.builder(),
.addPlugin(new XdsServerPlugin(...)), .service("/api", myService) and .build()
so the snippet (including XdsServerPlugin and Server.builder) is rendered with
Java syntax highlighting.
- Around line 174-180: The docs lack operational guidance for the blocking
install() call; update SERVER_PROPOSAL.md near the install() description to
specify a configurable timeout (e.g., installTimeoutMs) and default behavior,
document retry/backoff strategies and fallback options when the xDS control
plane is unavailable (e.g., fail fast vs continue with cached/default snapshot),
and add recommendations for health checks and startup probes during the blocking
phase (e.g., return STARTING vs UNHEALTHY, expose a non-blocking readiness
endpoint). Reference the install() entry, ConnectionAcceptor behavior, and
ServerTlsProvider resolution so readers know where timeouts/retries apply and
how health-check semantics should map during initialization.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0e9ed98d-f238-4f3a-a2fb-8949e72e1bae

📥 Commits

Reviewing files that changed from the base of the PR and between 842eefc and 76a662c.

📒 Files selected for processing (2)
  • xds/docs/SERVER_DESIGN.md
  • xds/docs/SERVER_PROPOSAL.md

Comment on lines +99 to +108
public final class ConnectionContext {
public SessionProtocol sessionProtocol();
public String sniHostname(); // empty string if no SNI
@Nullable public List<String> alpnProtocols(); // null if no ALPN
public InetSocketAddress localAddress();
public InetSocketAddress remoteAddress();
@Nullable public <T> T attr(AttributeKey<T> key);
public <T> void setAttr(AttributeKey<T> key, @Nullable T value);
}
```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Inconsistent null-handling in ConnectionContext API.

The API has inconsistent semantics for "not present" values:

  • sniHostname() returns an empty string when SNI is absent (non-null)
  • alpnProtocols() returns null when ALPN is absent (@Nullable)

This inconsistency can confuse API users and lead to inconsistent null-checking patterns. Consider aligning the semantics—either both use null to indicate absence, or both use empty/empty-list to indicate absence.

Recommendation: Use @Nullable String for sniHostname() to match alpnProtocols(), since null is a clearer signal of "not present" for optional connection attributes.

🔄 Proposed fix
 public final class ConnectionContext {
     public SessionProtocol sessionProtocol();
-    public String sniHostname();                     // empty string if no SNI
+    `@Nullable` public String sniHostname();           // null if no SNI
     `@Nullable` public List<String> alpnProtocols();   // null if no ALPN
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public final class ConnectionContext {
public SessionProtocol sessionProtocol();
public String sniHostname(); // empty string if no SNI
@Nullable public List<String> alpnProtocols(); // null if no ALPN
public InetSocketAddress localAddress();
public InetSocketAddress remoteAddress();
@Nullable public <T> T attr(AttributeKey<T> key);
public <T> void setAttr(AttributeKey<T> key, @Nullable T value);
}
```
public final class ConnectionContext {
public SessionProtocol sessionProtocol();
`@Nullable` public String sniHostname(); // null if no SNI
`@Nullable` public List<String> alpnProtocols(); // null if no ALPN
public InetSocketAddress localAddress();
public InetSocketAddress remoteAddress();
`@Nullable` public <T> T attr(AttributeKey<T> key);
public <T> void setAttr(AttributeKey<T> key, `@Nullable` T value);
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@xds/docs/SERVER_PROPOSAL.md` around lines 99 - 108, Align the null-handling
semantics by making sniHostname() nullable: change
ConnectionContext.sniHostname() to return "@Nullable String" (instead of empty
string) to match alpnProtocols() semantics; update the interface signature, any
javadoc/docs in SERVER_PROPOSAL.md, all implementations of ConnectionContext
(and their constructors/builders) to return null when SNI is absent, and adjust
callers/tests to handle null rather than empty string. Ensure Attribute:
reference sniHostname() and alpnProtocols() in the same style across the
codebase and run tests to catch call sites that assumed an empty string.

@jrhee17 jrhee17 marked this pull request as ready for review May 15, 2026 06:13
@codecov

codecov Bot commented May 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 0.00%. Comparing base (8150425) to head (76a662c).
⚠️ Report is 458 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff              @@
##               main   #6766       +/-   ##
============================================
- Coverage     74.46%       0   -74.47%     
============================================
  Files          1963       0     -1963     
  Lines         82437       0    -82437     
  Branches      10764       0    -10764     
============================================
- Hits          61385       0    -61385     
+ Misses        15918       0    -15918     
+ Partials       5134       0     -5134     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ikhoon ikhoon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The proposed implementation direction looks good to me.

```java
package com.linecorp.armeria.server;

public final class ConnectionContext {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit)

  • Should we make it an interface so that we can wrap it and override methods easily?
  • Expose Netty Channel as well?


@FunctionalInterface
public interface ConnectionAcceptor {
boolean accept(ConnectionContext ctx);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question) What does the returned boolean value indicate?

@minwoox minwoox left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 👍

@jrhee17 jrhee17 modified the milestones: 1.40.0, 1.41.0 Jun 10, 2026
@mergify

mergify Bot commented Jun 19, 2026

Copy link
Copy Markdown

Tick the box to add this pull request to the merge queue (same as @mergifyio queue).

  • Queue this pull request

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants