Rendezvous hashing node selector
Assign a key to one node from your list: user:42 across cache-a, cache-b and cache-c lands on cache-a, and stays there until the node list or the seed changes. Every node's score is shown so you can audit the pick. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Key
- user:42
- Nodes
- cache-a, cache-b, cache-c
- Seed
- Selected
- cache-a
- Node count
- 3
Rendezvous hashing, also called highest random weight hashing, assigns each key to exactly one node from a live set without a virtual-node ring. For every candidate node the algorithm hashes the key together with that node identifier, ranks the scores, and picks the winner. When a node joins or leaves, only keys that previously mapped to the departed node (or that now prefer the newcomer) move—the rest stay put—so cache hit rates and shard ownership remain stable under membership churn. This rendezvous hashing node selector accepts a routing key, a list of node ids, an optional cluster seed, and optional positive weights, then returns the selected node plus the full score table so you can audit or unit-test placement.
How rendezvous hashing chooses a node for a key
Consistent hashing popularized the idea of placing keys on a ring so that adding or removing a node remaps only a small fraction of keys. Rendezvous hashing solves the same load-balancing problem with a simpler contract: for each node in the current membership set, compute a score that depends only on the key and that node’s identity, then select the node with the highest score. The classic name “highest random weight” reflects that the hash behaves like a pseudorandom weight per pair.
Because the score for node A never depends on whether node B is present, removing B only affects keys for which B was previously the winner—every other key still prefers the same survivor. Adding a node C steals only those keys that score higher with C than with their former owner. That minimal disruption property is why caches, edge POPs, and sharded databases use rendezvous when they want balanced ownership without maintaining a large virtual-node ring.
When you supply positive weights parallel to the node list, the algorithm switches to weighted HRW: the hash is mapped to a unit interval u in (0,1] and the score becomes u raised to one over the weight, so heavier nodes win more often while remaining fully deterministic. Ties—rare with a 32-bit mix but possible—are broken by choosing the lexicographically smaller node id so two clients never disagree.
Where a rendezvous node selector earns its keep
Application developers use a rendezvous hashing node selector to pin user sessions, object shards, or rate-limit counters to a stable backend without standing up ZooKeeper rings or large consistent-hash libraries. CDN and multi-region edge teams map content keys onto POPs so cache affinity survives scale-out. Game and IoT fleets route device ids to simulation workers and only remesh the fraction of devices that preferred a node that left.
Data pipelines that partition Kafka-style keys across consumers can dry-run membership changes offline by feeding candidate node lists into the same pure function the workers will call.
What you can do with it
Cache and shard affinity
Map object or user keys onto cache replicas or database shards so membership changes remount only the keys that preferred the added or removed node.
Multi-region edge routing
Choose a POP or worker from a live healthy list for each content key, using optional weights for capacity skew across regions.
Offline rebalance dry-runs
Feed planned node lists into the same deterministic selector in CI to measure how many keys would move before you change production membership.
FAQ
What is rendezvous hashing (highest random weight)?
It scores every (key, node) pair with a hash and picks the highest score. Only keys that preferred a removed node—or prefer a newly added node—move; the rest stay put.
How do I select a node for a key?
Send key and nodes (one or more unique node ids). Optionally add seed for a cluster salt and weights for capacity skew. The response selected field is the winning node.
How is this different from consistent hashing?
Consistent hashing places keys and virtual nodes on a ring.
Can nodes have different capacities?
Yes. Pass weights as positive numbers parallel to nodes. The method switches to weighted HRW (u to the power of 1/weight) so heavier nodes win more often while remaining deterministic.
What happens to the other keys when a node is removed?
They stay where they were. A node's score depends only on the key and that node, so removing one moves only the keys it was winning, and adding a node takes only the keys that now score higher with it.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/dev/rendezvous-hash \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"key":"user:42","nodes":["cache-a","cache-b","cache-c"]}'const res = await fetch("https://api.kit.forhosting.com/dev/rendezvous-hash", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"key": "user:42",
"nodes": [
"cache-a",
"cache-b",
"cache-c"
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/dev/rendezvous-hash",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"key": "user:42",
"nodes": [
"cache-a",
"cache-b",
"cache-c"
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/dev/rendezvous-hash", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"key":"user:42","nodes":["cache-a","cache-b","cache-c"]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"key":"user:42","nodes":["cache-a","cache-b","cache-c"]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/dev/rendezvous-hash", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"key": "user:42",
"nodes": [
"cache-a",
"cache-b",
"cache-c"
]
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "dev.rendezvous_hash",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
The pure parse implementation is deterministic across browser and API paths, costs no model tokens, and never reaches the network.
How rendezvous hashing chooses a node for a key
This endpoint implements unweighted HRW with a 32-bit FNV-1a mix of an optional seed, the key, and each node id: the raw unsigned hash is the score, so comparisons are integer-stable.
Input contract, response shape, and validation rules
Optional weights is an array of positive finite numbers with the same length as nodes; omit it for equal-weight unweighted rendezvous. Example: key user:42 with nodes cache-a, cache-b, cache-c yields a single selected cache name that will not change until the membership set or seed changes. Pair the selector with your own health checks—pass only healthy node ids in the nodes array—so failed hosts drop out of the score race without special case logic inside the hash. POST a JSON body with key (required non-empty string after trim; alias object_key) and nodes (required array of one to one thousand distinct non-empty node id strings; alias members). Optional seed (alias salt) is a string salt prepended to the key so independent clusters can map the same business key differently without colliding in the score table; omit it or pass an empty string for no salt. Empty keys, empty node lists, null entries, duplicate node ids, non-positive weights, or a weights length that does not match nodes fail with invalid_input and are not billed. On success the response echoes key and seed, names the selected node, reports node_count, sets method to rendezvous_hrw or weighted_rendezvous_hrw, and returns scores: an array of objects each with node, weight, score, and the underlying hash integer, sorted by descending score then ascending node name. That full table is intentional: load-test harnesses and code reviews often need to prove why a key landed on a particular host.
Where a rendezvous node selector earns its keep
Content sites that rank for rendezvous hashing or highest random weight hashing benefit from a live free browser tool whose answers match the paid API byte-for-byte.
Technical questions
What does the rendezvous hashing node selector cost?
The browser tool is free. API requests use prepaid KIT balance at $0.002 per successful call; invalid input is not billed.