Peer Operations Overview
Guide for connecting to, monitoring, and operating Convex peer nodes.
What is Peer Operations?
Peer Operations covers everything from connecting to existing peers to running your own peer infrastructure:
For Developers (connecting to peers):
- Connection Types - HTTP vs binary protocol
- Network Verification - Genesis hash and health checks
- Performance - Optimization and monitoring
For Operators (running peers):
- Staking & Registration - Stake coins and register your peer
- Manual Deployment - Install and configure manually
- Docker Deployment - Deploy with Docker/Compose
- Hosting Options - Infrastructure and requirements
- Security - Secure your peer infrastructure
- Troubleshooting - Diagnose and fix issues
Connection Types
Convex peers support two connection protocols with different performance characteristics.
HTTP Protocol (REST API)
Recommended for: Web applications, general development
Connection:
// Java
Convex convex = Convex.connect("https://peer.convex.live");
// TypeScript
const convex = new Convex('https://peer.convex.live');
# Python
convex = Convex('https://peer.convex.live')
Characteristics:
- Protocol: HTTPS with JSON payloads
- Port: 18888 (default)
- Latency: 10-50ms typical
- Firewall: Works through HTTP proxies
- Connection: Stateless
Binary Protocol
Recommended for: High-performance applications
Connection:
// Java
import java.net.InetSocketAddress;
InetSocketAddress addr = InetSocketAddress.createUnresolved(
"peer.convex.live",
18888
);
Convex convex = Convex.connect(addr);
Characteristics:
- Protocol: Custom binary over TCP
- Port: 18888 (default)
- Latency: 5-20ms typical
- Connection: Persistent stateful
- Throughput: Higher than HTTP
Connection Configuration
Timeouts:
Convex convex = Convex.connect("https://peer.convex.live");
convex.setTimeout(Duration.ofSeconds(30));
Connection Pooling (for high concurrency):
import java.util.concurrent.ConcurrentLinkedQueue;
class ConvexConnectionPool {
private final ConcurrentLinkedQueue<Convex> pool = new ConcurrentLinkedQueue<>();
private final String endpoint;
public ConvexConnectionPool(String endpoint) {
this.endpoint = endpoint;
}
public Convex acquire() throws Exception {
Convex convex = pool.poll();
if (convex == null) {
convex = Convex.connect(endpoint);
}
return convex;
}
public void release(Convex convex) {
pool.offer(convex);
}
}
Network Health and Status
Check Network Availability
import convex.api.Convex;
import convex.core.Result;
import convex.core.lang.Reader;
Convex convex = Convex.connect("https://peer.convex.live");
// Query consensus state
Result result = convex.query(Reader.read("*state*")).get();
if (!result.isError()) {
System.out.println("✓ Network operational");
} else {
System.err.println("✗ Network issue: " + result.getErrorCode());
}
Query Network Metadata
// Peer information
Result peerInfo = convex.query(Reader.read("(get-peer-info)")).get();
// Current consensus point
Result consensus = convex.query(Reader.read("*state*")).get();
// Total accounts
Result accounts = convex.query(Reader.read("(count *accounts*)")).get();
// Memory usage
Result memory = convex.query(Reader.read("*memory*")).get();
Verifying Network Identity
Each network has a unique genesis hash. Always verify you're connected to the correct network.
Protonet Genesis Hash
0xb0e44f2a645abfa539f5b96b7a0eabb0f902866feaff0f7c12d1213e02333f13
Verify Connection
// Protonet genesis hash
String PROTONET_GENESIS = "0xb0e44f2a645abfa539f5b96b7a0eabb0f902866feaff0f7c12d1213e02333f13";
// Connect and verify
Convex convex = Convex.connect("https://peer.convex.live");
Result result = convex.query(Reader.read("*genesis*")).get();
String genesis = result.getValue().toString();
if (genesis.equals(PROTONET_GENESIS)) {
System.out.println("✓ Connected to Protonet");
} else {
System.err.println("⚠ Warning: Unknown network");
System.err.println("Genesis: " + genesis);
}
TypeScript Example
const PROTONET_GENESIS = '0xb0e44f2a645abfa539f5b96b7a0eabb0f902866feaff0f7c12d1213e02333f13';
const convex = new Convex('https://peer.convex.live');
const result = await convex.query('*genesis*');
if (result.value.toString() === PROTONET_GENESIS) {
console.log('✓ Connected to Protonet');
} else {
console.warn('⚠ Unknown network:', result.value.toString());
}
Python Example
PROTONET_GENESIS = "0xb0e44f2a645abfa539f5b96b7a0eabb0f902866feaff0f7c12d1213e02333f13"
convex = Convex('https://peer.convex.live')
result = convex.query('*genesis*')
if str(result.value) == PROTONET_GENESIS:
print("✓ Connected to Protonet")
else:
print(f"⚠ Unknown network: {result.value}")
Important Notes
- ⚠️ Testnets change genesis hash when they reset
- ⚠️ Local peers generate new genesis hash on startup
- ✅ Protonet genesis is stable - always verify for production
- 🔒 Prevents accidental connection to wrong network
Performance Optimization
Connection Performance
| Method | Latency | Throughput | Use Case |
|---|---|---|---|
| HTTP | 10-50ms | ~100 ops/sec | Web apps, general use |
| Binary | 5-20ms | ~500 ops/sec | High-performance apps |
| Local Peer | <1ms | ~10,000 ops/sec | Development, testing |
Best Practices
For Development:
- Use local peer for fastest iteration
- Binary protocol for integration tests
- Disable unnecessary logging
For Production:
- Use binary protocol for better throughput
- Implement connection pooling
- Monitor peer health proactively
- Verify genesis hash on startup
- Set appropriate timeouts
- Implement retry logic with exponential backoff
Monitoring Example
import java.util.concurrent.*;
public class PeerMonitor {
private final Convex convex;
private final ScheduledExecutorService scheduler =
Executors.newScheduledThreadPool(1);
public PeerMonitor(Convex convex) {
this.convex = convex;
}
public void startMonitoring() {
scheduler.scheduleAtFixedRate(() -> {
try {
Result result = convex.query(Reader.read("*state*")).get();
if (result.isError()) {
System.err.println("⚠ Peer health check failed");
} else {
System.out.println("✓ Peer healthy");
}
} catch (Exception e) {
System.err.println("