Pseudo-Links
A pseudo-link allows you to interpret any 40-bit index as a stateless, relation between a set of related entities. This means you can establish relationships between entities without storing any connection data - the relationship exists purely through shared bit patterns.
The key insight: by treating an index as structured coordinates (neighborhood, connector, island) rather than a scalar value, you can instantly navigate between related indices through simple bitwise operations. The indices can point to items in the same PseudoArray (same object type) or different arrays (like users and groups). When working with Pseudo-IDs, a pseudo-link operates on the 40-bit index component, while the world-seed and type-sequence remain unchanged.
In traditional systems, determining relationships requires database lookups or junction tables. With pseudo-links, you manipulate bits to calculate related indices - no database needed, no special encoding required. Any 40-bit value is valid; pseudo-links provide bitwise operations to construct, modify, and navigate through indices as if they were coordinates in a multi-dimensional space.
How It Works
Section titled “How It Works”A pseudo-link divides a 40-bit Index into three configurable zones:
Configurable Bit Layout:
- Island (High bits, bits 23-39): Configurable width (default: 17 bits). You specify this in the constructor. These bits determine sharding - they remain unchanged during relationship calculations, ensuring related indices always hash to the same partition.
- Neighborhood (Middle bits, bits 3-22): Configurable width (default: 20 bits). You specify this in the constructor. Indices sharing the same neighborhood and island bits are considered related.
- Connector (Low bits, bits 0-2): Calculated automatically as remaining bits (default: 3 bits = 40 - 17 island - 20 neighborhood). This is the “slot” that gets modified to navigate between related indices. With 3 bits, you get 8 possible relationships per neighborhood.
The bit layout is configurable. You choose islandBits and neighborhoodBits in the constructor. The remaining bits (40 - islandBits - neighborhoodBits) automatically become the connector. Choose your layout based on your requirements: more connector bits = more relationships per neighborhood, more island bits = finer sharding granularity.
Why this bit order? Island occupies the high bits to enable simple range-based sharding ( or ). This creates contiguous shard ranges: shard 0 contains indices [0, ), shard 1 contains [, ), etc. Connector sits on the low bits for efficient bit manipulation. Neighborhood uses the middle bits, grouping related entities together while preserving the island value.
Relationships are calculated by performing bitwise operations on the connector bits. The resolve() function replaces the connector segment with a new value, generating a related index that shares the same neighborhood and island bits.
For self-referencing relationships (where a model links to itself), use resolveWithTeleport() instead of resolve() to prevent entities from referencing themselves by XORing the neighborhood bits. See Same-Entity Relationships below.
PseudoLink Class
Section titled “PseudoLink Class”The Interface tab shows the PseudoLink API reference. Examples throughout this document assume this interface.
The Implementation tab contains a complete reference implementation useful for porting to other languages.
/** * Coordinate components of a 40-bit index */interface LinkComponents { island: number; neighborhood: number; connector: number;}
/** * PseudoLink * A coordinate system for manipulating 40-bit indices. * Provides O(1) navigation between related indices through bitwise operations. * Operates on plain numbers - no special encoding required. */declare class PseudoLink { /** * @param islandBits - Number of bits used for sharding (default: 17). * @param neighborhoodBits - Number of bits for grouping (default: 20). * The remaining bits (40 - islandBits - neighborhoodBits) become the connector. * Choose your layout based on requirements: more connectorBits = more relationships. */ constructor(islandBits: number, neighborhoodBits: number);
/** * Constructs a 40-bit index from coordinate components. * @param island - Island value (0 to maxIsland()). * @param neighborhood - Neighborhood value (0 to maxNeighborhood()). * @param connector - Connector value (0 to maxConnector()). * @returns A 40-bit index with the specified coordinates. */ public encode(island: number, neighborhood: number, connector: number): bigint;
/** * Extracts coordinate components from a 40-bit index. * @param index - Any 40-bit index value. * @returns The island, neighborhood, and connector components. */ public decode(index: bigint | number): LinkComponents;
/** * Calculates a related index by modifying the connector bits. * @param sourceIndex - Any 40-bit index value. * @param connector - The target connector value (0 to maxConnector()). * @returns A related index sharing the same neighborhood and island bits. */ public resolve(sourceIndex: bigint | number, connector: number): bigint;
/** * Resolves a relationship with neighborhood teleportation. * Prevents self-references by XORing the neighborhood bits. * * @param sourceIndex - Source 40-bit index value. * @param connector - The target connector value (0 to maxConnector()). * @param distance - XOR distance for neighborhood teleportation (typically 1). * @returns A related index in a parallel neighborhood (same island, different neighborhood). */ public resolveWithTeleport(sourceIndex: bigint | number, connector: number, distance: number): bigint;
/** Returns the maximum island value (2^islandBits - 1). */ public maxIsland(): number;
/** Returns the maximum neighborhood value (2^neighborhoodBits - 1). */ public maxNeighborhood(): number;
/** Returns the maximum connector value (2^connectorBits - 1). */ public maxConnector(): number;}/** * Coordinate components of a 40-bit index */interface LinkComponents { island: number; neighborhood: number; connector: number;}
/** * PseudoLink * A coordinate system for manipulating 40-bit indices. * Provides O(1) navigation between related indices through bitwise operations. * Operates on plain numbers - no special encoding required. */class PseudoLink { private readonly islandBits: bigint; private readonly connectorBits: bigint; private readonly neighborhoodBits: bigint; private readonly shift: bigint; private readonly connectorMask: bigint; private readonly islandMask: bigint; private readonly neighborhoodMask: bigint; private readonly indexLimit: bigint; private readonly _maxIsland: number; private readonly _maxNeighborhood: number; private readonly _maxConnector: number;
/** * @param islandBits - Number of bits used for sharding (default: 17). * @param neighborhoodBits - Number of bits for grouping (default: 20). * The remaining bits (40 - islandBits - neighborhoodBits) become the connector. * Choose your layout based on requirements: more connectorBits = more relationships. */ constructor(islandBits: number, neighborhoodBits: number) { this.islandBits = BigInt(islandBits); this.neighborhoodBits = BigInt(neighborhoodBits); this.connectorBits = 40n - this.islandBits - this.neighborhoodBits;
this.connectorMask = (1n << this.connectorBits) - 1n; this.neighborhoodMask = (1n << this.neighborhoodBits) - 1n; this.islandMask = (1n << this.islandBits) - 1n;
this._maxIsland = (1 << islandBits) - 1; this._maxConnector = (1 << connectorBits) - 1; this._maxNeighborhood = (1 << Number(this.neighborhoodBits)) - 1;
this.indexLimit = (1n << 40n) - 1n; }
/** * Constructs a 40-bit index from coordinate components. * @param island - Island value (0 to maxIsland()). * @param neighborhood - Neighborhood value (0 to maxNeighborhood()). * @param connector - Connector value (0 to maxConnector()). * @returns A 40-bit index with the specified coordinates. */ public encode(island: number, neighborhood: number, connector: number): bigint { if (island < 0 || island > this._maxIsland) { throw new Error(`Island ${island} out of bounds (0-${this._maxIsland}).`); } if (connector < 0 || connector > this._maxConnector) { throw new Error(`Connector ${connector} out of bounds (0-${this._maxConnector}).`); } if (neighborhood < 0 || neighborhood > this._maxNeighborhood) { throw new Error(`Neighborhood ${neighborhood} out of bounds (0-${this._maxNeighborhood}).`); }
const connectorPart = BigInt(connector) & this.connectorMask; const neighborhoodPart = (BigInt(neighborhood) & this.neighborhoodMask) << this.connectorBits; const islandPart = (BigInt(island) & this.islandMask) << (this.connectorBits + this.neighborhoodBits);
return islandPart | neighborhoodPart | connectorPart; }
/** * Extracts coordinate components from a 40-bit index. * @param index - Any 40-bit index value. * @returns The island, neighborhood, and connector components. */ public decode(index: bigint | number): LinkComponents { const bigIndex = BigInt(index) & this.indexLimit;
const connector = Number(bigIndex & this.connectorMask); const neighborhood = Number((bigIndex >> this.connectorBits) & this.neighborhoodMask); const island = Number((bigIndex >> (this.connectorBits + this.neighborhoodBits)) & this.islandMask);
return { island, neighborhood, connector }; }
/** * Calculates a related index by modifying the connector bits. * @param sourceIndex - Any 40-bit index value. * @param connector - The target connector value (0 to maxConnector()). * @returns A related index sharing the same neighborhood and island bits. */ public resolve(sourceIndex: bigint | number, connector: number): bigint { if (connector < 0 || connector > this._maxConnector) { throw new Error(`Connector ${connector} out of bounds (0-${this._maxConnector}).`); } const bigIndex = BigInt(sourceIndex) & this.indexLimit;
// Clear the connector window and inject the new connector value const clearedBase = bigIndex & ~this.connectorMask; return clearedBase | BigInt(connector); }
/** * Resolves a relationship with neighborhood teleportation. * Prevents self-references by XORing the neighborhood bits. * * @param sourceIndex - Source 40-bit index value. * @param connector - The target connector value (0 to maxConnector()). * @param distance - XOR distance for neighborhood teleportation (typically 1). * @returns A related index in a parallel neighborhood (same island, different neighborhood). */ public resolveWithTeleport(sourceIndex: bigint | number, connector: number, distance: number): bigint { if (connector < 0 || connector > this._maxConnector) { throw new Error(`Connector ${connector} out of bounds (0-${this._maxConnector}).`); }
const components = this.decode(sourceIndex);
// Teleport: XOR neighborhood bits const teleportedNeighborhood = (components.neighborhood ^ distance) & this._maxNeighborhood;
// Re-encode with teleported neighborhood return this.encode(components.island, teleportedNeighborhood, connector); }
/** * Returns the maximum island value. * @returns The maximum island value (2^islandBits - 1). */ public maxIsland(): number { return this._maxIsland; }
/** * Returns the maximum neighborhood value. * @returns The maximum neighborhood value (2^neighborhoodBits - 1). */ public maxNeighborhood(): number { return this._maxNeighborhood; }
/** * Returns the maximum connector value. * @returns The maximum connector value (2^connectorBits - 1). */ public maxConnector(): number { return this._maxConnector; }}Relationship Patterns
Section titled “Relationship Patterns”Pseudo-links enable several relationship patterns through coordinate manipulation. Unlike traditional database relationships, these patterns are stateless and deterministic—the relationship exists purely through shared bit patterns.
Linking Two Entities
Section titled “Linking Two Entities”Cross-Type Many-to-One Pattern
Use resolve() to navigate from one entity type to another at a specific connector. Multiple entities in the same neighborhood and island will resolve to the same related entity at that connector, creating a many-to-one relationship.
Coordinate Structure:
- Source entity at any index within a neighborhood (e.g., User at index
1000) - Use
resolve(sourceIndex, connector)to find related entity - All entities in the same neighborhood and island resolve to the same target entities
- Different connector values navigate to different related entities (e.g., connector 0 = primary address, connector 1 = billing address)
Characteristics:
- Cardinality: Many-to-one (multiple Users → one Address at connector 0)
- Navigation: Use
resolve()with specific connector value, access - Shard Safety: Automatic (same island = same shard)
- Sharing: All users in neighborhood N:1000 share the same addresses at each connector
- Use Case: Shared resources (Users→Addresses, Orders→ShippingMethods)
Example: Users with the same island and neighborhood but different connectors all resolve to the same primary address when using connector 0.
import "github.com/pseudata/pseudata"
const worldSeed = int64(42)
users := pseudata.NewUserArray(worldSeed)addresses := pseudata.NewAddressArray(worldSeed)link := pseudata.NewPseudoLink(17, 20)
// Alice at explicit coordinates (I:1, N:1000, C:0)aliceIdx := link.Encode(1, 1000, 0)alice := users.At(aliceIdx)
// Find Alice's primary address at connector 0 (same I:1, N:1000)addressIdx := link.Resolve(aliceIdx, 0)address := addresses.At(addressIdx)import dev.pseudata.UserArray;import dev.pseudata.PseudoLink;
final long WORLD_SEED = 42L;
UserArray users = new UserArray(WORLD_SEED);AddressArray addresses = new AddressArray(WORLD_SEED);PseudoLink link = new PseudoLink(17, 20);
// Alice at explicit coordinates (I:1, N:1000, C:0)long aliceIdx = link.encode(1, 1000, 0);User alice = users.at(aliceIdx);
long addressIdx = link.resolve(aliceIdx, 0);Address address = addresses.at(addressIdx);from pseudata import UserArray, PseudoLink
WORLD_SEED = 42
users = UserArray(WORLD_SEED)addresses = AddressArray(WORLD_SEED)link = PseudoLink(17, 20)
# Alice at explicit coordinates (I:1, N:1000, C:0)alice_idx = link.encode(1, 1000, 0)alice = users.at(alice_idx)
address_idx = link.resolve(alice_idx, 0)address = addresses.at(address_idx)import { UserArray, PseudoLink } from '@pseudata/core';
const WORLD_SEED = 42n;
const users = new UserArray(WORLD_SEED);const addresses = new AddressArray(WORLD_SEED);const link = new PseudoLink(17, 20);
// Alice at explicit coordinates (I:1, N:1000, C:0)const aliceIdx = link.encode(1, 1000, 0);const alice = users.at(aliceIdx);
const addressIdx = link.resolve(aliceIdx, 0);const address = addresses.at(addressIdx);One-to-Many
Section titled “One-to-Many”Within-Neighborhood Complete Graph Pattern
Entities sharing the same island and neighborhood but different connector values form a complete graph—every entity relates to every other entity in that cell. With 3 connector bits, you get 8 related entities (connectors 0-7).
Coordinate Structure:
- Fixed: island (e.g.,
1) and neighborhood (e.g.,1000) - Variable: connector (0 to )
- Use
resolve(index, c)to navigate between connectors
Characteristics:
- Cardinality: Many-to-many (8 entities with default 3 connector bits)
- Navigation: Change connector value, preserving island and neighborhood
- Shard Safety: Guaranteed (all share same island bits)
- Complete Graph: Every entity in the cell relates to every other entity
- Use Case: Symmetric groups (Users in a chatroom, Students in a class section)
Mathematical Property: This creates where . With 3 connector bits, every neighborhood contains a complete graph of 8 vertices.
Limitation: Fixed cardinality—you cannot add more relationships than available connector slots. Increasing connector bits reduces neighborhood bits, changing the trade-off between relationship density and grouping capacity.
import "github.com/pseudata/pseudata"
const worldSeed = int64(42)
users := pseudata.NewUserArray(worldSeed)groups := pseudata.NewGroupArray(worldSeed)link := pseudata.NewPseudoLink(17, 20)
// Alice at explicit coordinates (I:1, N:1000, C:0)aliceIdx := link.Encode(1, 1000, 0)alice := users.At(aliceIdx)
// Find all groups Alice belongs to (iterate through all connector slots)userGroups := []Group{}for slot := 0; slot <= link.MaxConnector(); slot++ { groupIdx := link.Resolve(aliceIdx, slot) userGroups = append(userGroups, groups.At(groupIdx))}import dev.pseudata.UserArray;import dev.pseudata.PseudoLink;
final long WORLD_SEED = 42L;
UserArray users = new UserArray(WORLD_SEED);GroupArray groups = new GroupArray(WORLD_SEED);PseudoLink link = new PseudoLink(17, 20);
// Alice at explicit coordinates (I:1, N:1000, C:0)long aliceIdx = link.encode(1, 1000, 0);User alice = users.at(aliceIdx);List<Group> userGroups = new ArrayList<>();
for (int slot = 0; slot <= link.maxConnector(); slot++) { long groupIdx = link.resolve(aliceIdx, slot); userGroups.add(groups.at(groupIdx));}from pseudata import UserArray, PseudoLink
WORLD_SEED = 42
users = UserArray(WORLD_SEED)groups = GroupArray(WORLD_SEED)link = PseudoLink(17, 20)
# Alice at explicit coordinates (I:1, N:1000, C:0)alice_idx = link.encode(1, 1000, 0)alice = users.at(alice_idx)
# Find all groups Alice belongs touser_groups = [ groups.at(link.resolve(alice_idx, slot)) for slot in range(0, link.max_connector() + 1)]import { UserArray, PseudoLink } from '@pseudata/core';
const WORLD_SEED = 42n;
const users = new UserArray(WORLD_SEED);const groups = new GroupArray(WORLD_SEED);const link = new PseudoLink(17, 20);
// Alice at explicit coordinates (I:1, N:1000, C:0)const aliceIdx = link.encode(1, 1000, 0);const alice = users.at(aliceIdx);
const userGroups = Array.from({ length: link.maxConnector() + 1 }, (_, i) => { const groupIdx = link.resolve(aliceIdx, i); return groups.at(groupIdx);});Many-to-One
Section titled “Many-to-One”Single Connector Selection Pattern
A specialization of the one-to-many pattern where you use a single connector value by convention. Multiple entities in the same neighborhood and island but different connector positions all resolve to the same target entity at a specific connector, creating a many-to-one relationship.
Coordinate Structure:
- Source entities in the same neighborhood and island (different connectors)
- Fixed target connector by convention (e.g., always use connector 0 for “primary”)
- All source entities resolve to the same target entity at that connector
Characteristics:
- Cardinality: Many-to-one (multiple Users → one Group at connector 0)
- Navigation: Use
resolve()with fixed connector value - Shard Safety: Maintained through same island
- Convention: Application defines semantic meaning (e.g., connector 0 = primary group)
- Use Case: Primary associations (Users→PrimaryGroup, Orders→DefaultWarehouse)
Example: Users at different connector positions within the same neighborhood (C:0, C:1, C:2, etc.) all use connector 0 to find their shared primary group.
import "github.com/pseudata/pseudata"
const worldSeed = int64(42)
users := pseudata.NewUserArray(worldSeed)groups := pseudata.NewGroupArray(worldSeed)link := pseudata.NewPseudoLink(17, 20)
// Alice at explicit coordinates (I:1, N:1000, C:0)aliceIdx := link.Encode(1, 1000, 0)alice := users.At(aliceIdx)
// Find Alice's primary group (connector 0)primaryGroupIdx := link.Resolve(aliceIdx, 0)primaryGroup := groups.At(primaryGroupIdx)import dev.pseudata.UserArray;import dev.pseudata.PseudoLink;
final long WORLD_SEED = 42L;
UserArray users = new UserArray(WORLD_SEED);GroupArray groups = new GroupArray(WORLD_SEED);PseudoLink link = new PseudoLink(17, 20);
// Alice at explicit coordinates (I:1, N:1000, C:0)long aliceIdx = link.encode(1, 1000, 0);User alice = users.at(aliceIdx);
long primaryGroupIdx = link.resolve(aliceIdx, 0);Group primaryGroup = groups.at(primaryGroupIdx);from pseudata import UserArray, PseudoLink
WORLD_SEED = 42
users = UserArray(WORLD_SEED)groups = GroupArray(WORLD_SEED)link = PseudoLink(17, 20)
# Alice at explicit coordinates (I:1, N:1000, C:0)alice_idx = link.encode(1, 1000, 0)alice = users.at(alice_idx)
primary_group_idx = link.resolve(alice_idx, 0)primary_group = groups.at(primary_group_idx)import { UserArray, PseudoLink } from '@pseudata/core';
const WORLD_SEED = 42n;
const users = new UserArray(WORLD_SEED);const groups = new GroupArray(WORLD_SEED);const link = new PseudoLink(17, 20);
// Alice at explicit coordinates (I:1, N:1000, C:0)const aliceIdx = link.encode(1, 1000, 0);const alice = users.at(aliceIdx);
const primaryGroupIdx = link.resolve(aliceIdx, 0);const primaryGroup = groups.at(primaryGroupIdx);Same-Entity Relationships
Section titled “Same-Entity Relationships”Neighborhood Teleportation Pattern
When a model links to itself (e.g., User → User for manager relationships), naive approaches can create self-references where an entity points to itself. Pseudata solves this with neighborhood teleportation using the resolveWithTeleport() method.
The Problem:
Without teleportation:Source: Island=1, Neighborhood=1000, Connector=0Target: Island=1, Neighborhood=1000, Connector=0❌ Same entity! (self-reference)The Solution:
With distance=1 teleportation:Source: Island=1, Neighborhood=1000, Connector=0Target: Island=1, Neighborhood=1001, Connector=0 (1000 XOR 1 = 1001)✅ Different entity! (no self-reference)How It Works:
- The
distanceparameter is XORed with the neighborhood bits distance: 1teleports from neighborhood 1000 to 1001- Same island (shard-safe), different neighborhood = different entity
- Mathematical guarantee:
Characteristics:
- Cardinality: Prevents self-references automatically
- Navigation: Use
resolveWithTeleport(sourceIndex, connector, distance) - Shard Safety: Maintained (same island value)
- Use Case: Organizational hierarchies (Employee→Manager), mentorship, buddy systems
Pattern Example: Manager Hierarchy
Employee at N:1000 → Manager at N:1001 (distance=1)Manager navigates back to find all reports at N:1000import "github.com/pseudata/pseudata"
users := pseudata.NewUserArray(42)link := users.LinkAt(1000)
// Forward: Find manager (teleport to parallel neighborhood)manager := link.Manager() // Uses ResolveWithTeleport(index, 0, 1)fmt.Printf("%s reports to %s\n", link.Me().Name, manager.Name)
// Reverse: Find direct reports (teleport back)fmt.Printf("%s manages:\n", link.Me().Name)for report := range link.Directs() { fmt.Printf(" - %s\n", report.Name)}import dev.pseudata.UserArray;
UserArray users = new UserArray(42L);UserLink link = users.linkAt(1000);
// Forward: Find manager (teleport to parallel neighborhood)User manager = link.manager(); // Uses resolveWithTeleport(index, 0, 1)System.out.printf("%s reports to %s%n", link.me().getName(), manager.getName());
// Reverse: Find direct reports (teleport back)System.out.printf("%s manages:%n", link.me().getName());for (User report : link.directs()) { System.out.printf(" - %s%n", report.getName());}from pseudata import UserArray
users = UserArray(42)link = users.link_at(1000)
# Forward: Find manager (teleport to parallel neighborhood)manager = link.manager() # Uses resolve_with_teleport(index, 0, 1)print(f"{link.me().name} reports to {manager.name}")
# Reverse: Find direct reports (teleport back)print(f"{link.me().name} manages:")for report in link.directs(): print(f" - {report.name}")import { UserArray } from '@pseudata/core';
const users = new UserArray(42n);const link = users.linkAt(1000);
// Forward: Find manager (teleport to parallel neighborhood)const manager = link.manager(); // Uses resolveWithTeleport(index, 0, 1)console.log(`${link.me().name} reports to ${manager.name}`);
// Reverse: Find direct reports (teleport back)console.log(`${link.me().name} manages:`);for (const report of link.directs()) { console.log(` - ${report.name}`);}Multiple Self-Relations:
Use different distance values to teleport to unique parallel neighborhoods:
Employee at Neighborhood 1000: - manager() with distance=1 → Neighborhood 1001 - mentor() with distance=3 → Neighborhood 1003 - buddy() with distance=5 → Neighborhood 1005Each relationship uses resolveWithTeleport() with a different distance to guarantee no collisions between relationship types.
Direct Usage Example:
const link = new PseudoLink(17, 20);
// Employee at index with neighborhood 1000const employeeIdx = link.encode(1, 1000, 0);
// Find manager in parallel neighborhood (1000 XOR 1 = 1001)const managerIdx = link.resolveWithTeleport(employeeIdx, 0, 1);
// Find mentor in different parallel neighborhood (1000 XOR 3 = 1003)const mentorIdx = link.resolveWithTeleport(employeeIdx, 1, 3);See the Using Relations guide for complete examples with the @link decorator and generated Link classes.
Bidirectional Navigation
Section titled “Bidirectional Navigation”Symmetric and Convention-Based Patterns
Bidirectional relationships depend on the pattern used:
Within-Neighborhood (Automatic Symmetry):
- Given index at (I:1, N:1000, C:0), resolve to C:3 → related entity
- From that entity at (I:1, N:1000, C:3), resolve back to C:0 → original entity
- Symmetry is mathematical—both directions use the same coordinate system
- No storage or convention needed
Cross-Neighborhood (Convention-Based):
- Relationship is unidirectional by default (Alice → Bob)
- Bidirectional requires conventions or stored mappings
- Forward: Alice (N:1000) → Bob (N:2000) via construction
- Reverse: Bob (N:2000) → Alice (N:1000) via coordinate convention or lookup table
- More flexible but requires application-level logic
Design Choice: Use within-neighborhood for automatic symmetric relationships (friendships, group membership). Use cross-neighborhood when direction matters or cardinality needs control.
import "github.com/pseudata/pseudata"
const worldSeed = int64(42)
users := pseudata.NewUserArray(worldSeed)link := pseudata.NewPseudoLink(17, 20)
// Alice in neighborhood 1000aliceIdx := link.Encode(1, 1000, 0)alice := users.At(aliceIdx)
// Bob (mentor) in neighborhood 2000mentorIdx := link.Encode(1, 2000, 0)mentor := users.At(mentorIdx)
// Navigate BACK: Given mentor's index, construct mentee's index// Using convention: mentee = N:1000, mentor = N:2000menteeIdx := link.Encode(1, 1000, 0) // Same as aliceIdxmentee := users.At(menteeIdx)
fmt.Printf("Bidirectional: %s's mentor is %s\n", alice.Name, mentor.Name)fmt.Printf("And %s's mentee is %s\n", mentor.Name, mentee.Name)import dev.pseudata.UserArray;import dev.pseudata.PseudoLink;
final long WORLD_SEED = 42L;
UserArray users = new UserArray(WORLD_SEED);PseudoLink link = new PseudoLink(17, 20);
// Alice in neighborhood 1000long aliceIdx = link.encode(1, 1000, 0);User alice = users.at(aliceIdx);
// Bob (mentor) in neighborhood 2000long mentorIdx = link.encode(1, 2000, 0);User mentor = users.at(mentorIdx);
// Navigate BACK: Given mentor's index, construct mentee's index// Using convention: mentee = N:1000, mentor = N:2000long menteeIdx = link.encode(1, 1000, 0); // Same as aliceIdxUser mentee = users.at(menteeIdx);
System.out.printf("Bidirectional: %s's mentor is %s%n", alice.getName(), mentor.getName());System.out.printf("And %s's mentee is %s%n", mentor.getName(), mentee.getName());from pseudata import UserArray, PseudoLink
WORLD_SEED = 42
users = UserArray(WORLD_SEED)link = PseudoLink(17, 20)
# Alice in neighborhood 1000alice_idx = link.encode(1, 1000, 0)alice = users.at(alice_idx)
# Bob (mentor) in neighborhood 2000mentor_idx = link.encode(1, 2000, 0)mentor = users.at(mentor_idx)
# Navigate BACK: Given mentor's index, construct mentee's index# Using convention: mentee = N:1000, mentor = N:2000mentee_idx = link.encode(1, 1000, 0) # Same as alice_idxmentee = users.at(mentee_idx)
print(f"Bidirectional: {alice.name}'s mentor is {mentor.name}")print(f"And {mentor.name}'s mentee is {mentee.name}")import { UserArray, PseudoLink } from '@pseudata/core';
const WORLD_SEED = 42n;
const users = new UserArray(WORLD_SEED);const link = new PseudoLink(17, 20);
// Alice in neighborhood 1000const aliceIdx = link.encode(1, 1000, 0);const alice = users.at(aliceIdx);
// Bob (mentor) in neighborhood 2000const mentorIdx = link.encode(1, 2000, 0);const mentor = users.at(mentorIdx);
// Navigate BACK: Given mentor's index, construct mentee's index// Using convention: mentee = N:1000, mentor = N:2000const menteeIdx = link.encode(1, 1000, 0); // Same as aliceIdxconst mentee = users.at(menteeIdx);
console.log(`Bidirectional: ${alice.name}'s mentor is ${mentor.name}`);console.log(`And ${mentor.name}'s mentee is ${mentee.name}`);Coordinate Bounds and Trade-offs
Section titled “Coordinate Bounds and Trade-offs”Configuration Impact on Relationship Capacity
The bit allocation determines relationship capacity:
Default Configuration (17 island, 3 connector, 20 neighborhood):
- Islands: (sharding granularity)
- Connectors: (relationships per neighborhood)
- Neighborhoods: (distinct groups)
Increasing Connector Bits (17 island, 5 connector, 18 neighborhood):
- More relationships per neighborhood:
- Fewer distinct neighborhoods:
- Trade-off: Deeper relationships vs. fewer groups
Increasing Island Bits (20 island, 3 connector, 17 neighborhood):
- Finer sharding: shards
- Fewer neighborhoods:
- Trade-off: Better distribution vs. grouping capacity
The configuration choice depends on your scenario’s relationship density, shard count, and grouping requirements.
When to Use
Section titled “When to Use”Pseudo-links are designed for creating deterministic, stateless relationships in test data and mock scenarios.
Ideal for:
- Many-to-many relationships: Users-Groups, Posts-Tags, Students-Courses
- Symmetric relationships: Friendships, peer connections, bidirectional links
- Asymmetric relationships: Follow/Follower patterns using slot conventions (e.g., connector 0 = following, connector 1 = followers)
- Cross-service testing: Microservices that need consistent relationship data without shared databases
- Distributed systems: Testing sharding logic with guaranteed shard-safe relationships
- Load testing: Generate billions of related entities without coordination overhead
- Deterministic demos: Consistent relationship patterns across all environments and languages
Not suitable for:
- Production databases: Use real foreign keys and junction tables for production data
- Dynamic relationships: Relationships that change frequently or unpredictably over time
- Complex graph queries: Deep traversal or pathfinding (use graph databases)
- Arbitrary cardinality: When you need unlimited relationships per entity (limited by connector bits)
Key advantage: Zero storage overhead with navigation - perfect for test scenarios where you need realistic, deterministic relationships without database complexity.
Deep Dive
Section titled “Deep Dive”This section details the bitwise mechanics that guarantee performance and sharding safety.
Key Principle: Pseudo-links perform pure bit manipulation on valid 40-bit integers. There is no special “encoding” - the functions simply read and write specific bit positions. Any 40-bit value (0 to 2^40-1) is valid input and produces valid output. The “relationship” exists because related indices share specific bit patterns (neighborhood and island bits).
The Transformation Function
Section titled “The Transformation Function”Let an index be defined as the concatenation of three bit-segments: Island (), Neighborhood (), and Connector ().
The pseudo-link resolution function treats the index as three segments and produces a new index by replacing the Connector segment with a target value . This is pure bit manipulation - reading and writing specific bit positions.
Symmetry Proof
Section titled “Symmetry Proof”Since and are preserved during the transformation, any two indices and are part of the same pseudo-link cell if and only if their Island and Neighborhood segments match:
and
This creates a Complete Graph within every neighborhood, where . All entities in the same pseudo-link cell are related to each other.
Sharding Invariance
Section titled “Sharding Invariance”Distributed systems often shard data by extracting the high-order bits. In a pseudo-link, given :
Because the resolution function only modifies bits at positions (the Connector and Neighborhood bits), the upper 17 bits (Island) are invariant:
Integration with Pseudo-IDs
Section titled “Integration with Pseudo-IDs”A pseudo-link operates on the 40-bit index component of Pseudo-IDs. When you create a PseudoID with encodeId(worldSeed, typeSeq, index), the index parameter is just a 40-bit number. PseudoLink provides a coordinate system for manipulating those bits to create relationships.
Key points:
- Pseudo-links work with the index component (40 bits) of PseudoIDs
- The world-seed and type-sequence remain unchanged
- Any 40-bit index value is valid - pseudo-links manipulate them through bitwise operations
- Enables stateless relationships between sets of entities
- Works across different types (e.g., User at index X relates to Group at related index Y)
import { encodeId, PseudoLink } from '@pseudata/core';
const worldSeed = 42n;const link = new PseudoLink(17, 20);
// Start with coordinates for entity A (e.g., User)const indexA = link.encode(1, 1000, 0);const userID = encodeId(worldSeed, 101, indexA); // Type 101 = Users
// Calculate related index for entity B (e.g., Group)const indexB = link.resolve(indexA, 2); // Same island & neighborhood, connector 2const groupID = encodeId(worldSeed, 102, indexB); // Type 102 = Groups
// The relationship exists through shared bit patterns in the indicesSee Also
Section titled “See Also”- Pseudo-IDs - Learn about the complete pseudo-id structure and how the 40-bit index component works with pseudo-links
- Pseudo-Arrays - Understand how pseudo-arrays use indices to provide access to deterministic mock data
- Primitives - Learn about the generator functions that can use indices constructed with pseudo-links
© 2025 Pseudata Project. Open Source under Apache License 2.0. · RSS Feed