kubo/docs/delegated-routing.md
Marcin Rataj 447109df64
Some checks failed
CodeQL / codeql (push) Has been cancelled
Docker Check / lint (push) Has been cancelled
Docker Check / build (push) Has been cancelled
Gateway Conformance / gateway-conformance (push) Has been cancelled
Gateway Conformance / gateway-conformance-libp2p-experiment (push) Has been cancelled
Go Build / go-build (push) Has been cancelled
Go Check / go-check (push) Has been cancelled
Go Lint / go-lint (push) Has been cancelled
Go Test / unit-tests (push) Has been cancelled
Go Test / cli-tests (push) Has been cancelled
Go Test / example-tests (push) Has been cancelled
Interop / interop-prep (push) Has been cancelled
Sharness / sharness-test (push) Has been cancelled
Spell Check / spellcheck (push) Has been cancelled
Interop / helia-interop (push) Has been cancelled
Interop / ipfs-webui (push) Has been cancelled
docs: clarify Routing.Type=custom as experimental (#11111)
* docs: mark custom routing as experimental

reorganize Routing.Type section for clarity, group production and
experimental options, consolidate DHT explanation, add limitations
section to delegated-routing.md documenting that HTTP-only routing
cannot provide content reliably

* chore(config): reorder Routing sections and improve callout formatting

move DelegatedRouters after Type, add config option names to CAUTION headers

* docs: address reviewer feedback on config.md

- clarify that `auto` can be combined with custom URLs in `Routing.DelegatedRouters`
- rename headers for consistency: `Routing.Routers.[name].Type`, `Routing.Routers.[name].Parameters`, `Routing.Methods`
- replace deprecated Strategic Providing reference with `Provide.*` config
- remove outdated caveat about 0.39 sweep limitation
- wording: "likely suffer" → "will be most affected"

* docs: remove redundant Summary section from delegated-routing.md

the IMPORTANT callout and Motivation section already cover what users
need to know. historical version info was noise for researchers trying
to configure custom routing.

addresses reviewer feedback from #11111.

---------

Co-authored-by: Daniel Norman <2color@users.noreply.github.com>
Co-authored-by: Andrew Gillis <11790789+gammazero@users.noreply.github.com>
2026-01-11 00:39:30 +01:00

13 KiB
Raw Permalink Blame History

Delegated Routing Notes

  • Status Date: 2025-12

Important

Most users are best served by setting delegated HTTP router URLs in Routing.DelegatedRouters and Routing.Type to auto or autoclient, rather than using custom routing with Routing.Routers and Routing.Methods directly.

The rest of this documentation describes experimental features intended only for researchers and advanced users.


Custom Multi-Router Configuration (Experimental)

Caution

Routing.Type=custom with Routing.Routers and Routing.Methods is EXPERIMENTAL.

This feature is provided for research and testing purposes only. It is not suitable for production use.

  • The configuration format and behavior may change without notice between Kubo releases.
  • Bugs and regressions affecting custom routing may not be prioritized or fixed promptly.
  • HTTP-only routing configurations (without DHT) cannot reliably provide content to the network (👉 see Limitations below).

For production deployments, use Routing.Type=auto (default) or Routing.Type=autoclient with Routing.DelegatedRouters.

Motivation

The actual routing implementation is not enough. Some users need to have more options when configuring the routing system. The new implementations should be able to:

  • Be user-friendly and easy enough to configure, but also versatile
  • Configurable Router execution order
    • Delay some of the Router methods execution when they will be executed on parallel
  • Configure which method of a giving router will be used
  • Mark some router methods as mandatory to make the execution fails if that method fails

Detailed design

Configuration file description

The Routing configuration section will contain the following keys:

Type

Type will be still in use to avoid complexity for the user that only wants to use Kubo with the default behavior. We are going to add a new type, custom, that will use the new router systems. none type will deactivate all routers, default dht and delegated ones.

Routers

Routers will be a key-value list of routers that will be available to use. The key is the router name and the value is all the needed configurations for that router. the Type will define the routing kind. The main router types will be http and dht, but we will implement two special routers used to execute a set of routers in parallel or sequentially: parallel router and sequential router.

Depending on the routing type, it will use different parameters:

HTTP

Params:

Amino DHT

Params:

  • "Mode": Mode used by the Amino DHT. Possible values: "server", "client", "auto"
  • "AcceleratedDHTClient": Set to true if you want to use the experimentalDHT.
  • "PublicIPNetwork": Set to true to create a WAN Amino DHT. Set to false to create a LAN DHT.
Parallel

Params:

  • Routers: A list of routers that will be executed in parallel:
    • Name:string: Name of the router. It should be one of the previously added to Routers list.
    • Timeout:duration: Local timeout. It accepts strings compatible with Go time.ParseDuration(string). Time will start counting when this specific router is called, and it will stop when the router returns, or we reach the specified timeout.
    • ExecuteAfter:duration: Providing this param will delay the execution of that router at the specified time. It accepts strings compatible with Go time.ParseDuration(string).
    • IgnoreErrors:bool: It will specify if that router should be ignored if an error occurred.
  • Timeout:duration: Global timeout. It accepts strings compatible with Go time.ParseDuration(string).
Sequential

Params:

  • Routers: A list of routers that will be executed in order:
    • Name:string: Name of the router. It should be one of the previously added to Routers list.
    • Timeout:duration: Local timeout. It accepts strings compatible with Go time.ParseDuration(string). Time will start counting when this specific router is called, and it will stop when the router returns, or we reach the specified timeout.
    • IgnoreErrors:bool: It will specify if that router should be ignored if an error occurred.
  • Timeout:duration: Global timeout. It accepts strings compatible with Go time.ParseDuration(string).

Methods

Methods:map will define which routers will be executed per method. The key will be the name of the method: "provide", "find-providers", "find-peers", "put-ipns", "get-ipns". All methods must be added to the list. This will make configuration discoverable giving good errors to the user if a method is missing.

The value will contain:

  • RouterName:string: Name of the router. It should be one of the previously added to Routers list.

Configuration file example:

"Routing": {
  "Type": "custom",
  "Routers": {
    "http-delegated": {
      "Type": "http",
      "Parameters": {
        "Endpoint": "https://delegated-ipfs.dev" // /routing/v1 (https://specs.ipfs.tech/routing/http-routing-v1/)
      }
    },
    "dht-lan": {
      "Type": "dht",
      "Parameters": {
        "Mode": "server",
        "PublicIPNetwork": false,
        "AcceleratedDHTClient": false
      }
    },
    "dht-wan": {
      "Type": "dht",
      "Parameters": {
        "Mode": "auto",
        "PublicIPNetwork": true,
        "AcceleratedDHTClient": false
      }
    },
    "find-providers-router": {
      "Type": "parallel",
      "Parameters": {
        "Routers": [
          {
            "RouterName": "dht-lan",
            "IgnoreErrors": true
          },
          {
            "RouterName": "dht-wan"
          },
          {
            "RouterName": "http-delegated"
          }
        ]
      }
    },
    "provide-router": {
      "Type": "parallel",
      "Parameters": {
        "Routers": [
          {
            "RouterName": "dht-lan",
            "IgnoreErrors": true
          },
          {
            "RouterName": "dht-wan",
            "ExecuteAfter": "100ms",
            "Timeout": "100ms"
          },
          {
            "RouterName": "http-delegated",
            "ExecuteAfter": "100ms"
          }
        ]
      }
    },
    "get-ipns-router": {
      "Type": "sequential",
      "Parameters": {
        "Routers": [
          {
            "RouterName": "dht-lan",
            "IgnoreErrors": true
          },
          {
            "RouterName": "dht-wan",
            "Timeout": "300ms"
          },
          {
            "RouterName": "http-delegated",
            "Timeout": "300ms"
          }
        ]
      }
    },
    "put-ipns-router": {
      "Type": "parallel",
      "Parameters": {
        "Routers": [
          {
            "RouterName": "dht-lan"
          },
          {
            "RouterName": "dht-wan"
          },
          {
            "RouterName": "http-delegated"
          }
        ]
      }
    }
  },
  "Methods": {
    "find-providers": {
      "RouterName": "find-providers-router"
    },
    "provide": {
      "RouterName": "provide-router"
    },
    "get-ipns": {
      "RouterName": "get-ipns-router"
    },
    "put-ipns": {
      "RouterName": "put-ipns-router"
    }
  }
}

Error cases

  • If any of the routers fails, the output will be an error by default.
  • You can use IgnoreErrors:true to ignore errors for a specific router output
  • To avoid any error at the output, you must ignore all router errors.

Implementation Details

Methods

All routers must implement the routing.Routing interface:

type Routing interface {
    ContentRouting
    PeerRouting
    ValueStore

    Bootstrap(context.Context) error
}

All methods involved:

type Routing interface {
    Provide(context.Context, cid.Cid, bool) error
    FindProvidersAsync(context.Context, cid.Cid, int) <-chan peer.AddrInfo
    
    FindPeer(context.Context, peer.ID) (peer.AddrInfo, error)

    PutValue(context.Context, string, []byte, ...Option) error
    GetValue(context.Context, string, ...Option) ([]byte, error)
    SearchValue(context.Context, string, ...Option) (<-chan []byte, error)

    Bootstrap(context.Context) error
}

We can configure which methods will be used per routing implementation. Methods names used in the configuration file will be:

  • Provide: "provide"
  • FindProvidersAsync: "find-providers"
  • FindPeer: "find-peers"
  • PutValue: "put-ipns"
  • GetValue, SearchValue: "get-ipns"
  • Bootstrap: It will be always executed when needed.

Routers

We need to implement the parallel and sequential routers and stop using routinghelpers.Tiered router implementation.

Add cycle detection to avoid to user some headaches.

Also we need to implement an internal router, that will define the router used per method.

Other considerations

  • We need to refactor how DHT routers are created to be able to use and add any amount of custom DHT routers.
  • We need to add a new custom router type to be able to use the new routing system.
  • Bitswap WANT broadcasting is not included on this document, but it can be added in next iterations.
  • This document will live in docs/design-notes for historical reasons and future reference.

Test fixtures

As test fixtures we can add different use cases here and see how the configuration will look like.

Mimic previous dual DHT config

"Routing": {
  "Type": "custom",
  "Routers": {
    "dht-lan": {
      "Type": "dht",
      "Parameters": {
        "Mode": "server",
        "PublicIPNetwork": false
      }
    },
    "dht-wan": {
      "Type": "dht",
      "Parameters": {
        "Mode": "auto",
        "PublicIPNetwork": true
      }
    },
    "parallel-dht-strict": {
      "Type": "parallel",
      "Parameters": {
        "Routers": [
          {
            "RouterName": "dht-lan"
          },
          {
            "RouterName": "dht-wan"
          }
        ]
      }
    },
    "parallel-dht": {
      "Type": "parallel",
      "Parameters": {
        "Routers": [
          {
            "RouterName": "dht-lan",
            "IgnoreError": true
          },
          {
            "RouterName": "dht-wan"
          }
        ]
      }
    }
  },
  "Methods": {
    "provide": {
      "RouterName": "dht-wan"
    },
    "find-providers": {
      "RouterName": "parallel-dht-strict"
    },
    "find-peers": {
      "RouterName": "parallel-dht-strict"
    },
    "get-ipns": {
      "RouterName": "parallel-dht"
    },
    "put-ipns": {
      "RouterName": "parallel-dht"
    }
  }
}

Compatibility

We need to create a config migration using fs-repo-migrations. We should remove the Routing.Type param and add the configuration specified previously.

We don't need to create any config migration! To avoid to the users the hassle of understanding how the new routing system works, we are going to keep the old behavior. We will add the Type custom to make available the new Routing system.

Security

No new security implications or considerations were found.

Alternatives

I got ideas from all of the following links to create this design document:

Limitations

HTTP-only routing cannot reliably provide content

Configurations that use only HTTP routers (without any DHT router) are unable to reliably announce content (provider records) to the network.

This limitation exists because:

  1. No standardized HTTP API for providing: The Routing V1 HTTP API spec only defines read operations (GET /routing/v1/providers/{cid}). The write operation (PUT /routing/v1/providers) was never standardized.

  2. Legacy experimental API: The only available HTTP providing mechanism is an undocumented PUT /routing/v1/providers request format called ProvideBitswap, which is a historical experiment. See IPIP-526 for ongoing discussion about formalizing HTTP-based provider announcements.

  3. Provider system integration: Kubo's default provider system (Provide.DHT.SweepEnabled=true since v0.38) is designed for DHT-based providing. When no DHT is configured, the provider system may silently skip HTTP routers or behave unexpectedly.

Workarounds for testing:

If you need to test HTTP providing, you can try:

  • Setting Provide.DHT.SweepEnabled=false to use the legacy provider system
  • Including at least one DHT router in your custom configuration alongside HTTP routers

These workarounds are not guaranteed to work across Kubo versions and should not be relied upon for production use.

Copyright and related rights waived via CC0.