Keep-Alive
Reduce latency by reusing HTTP connections instead of establishing new ones for each request.
Overview
BlockSprint supports HTTP/1.1 persistent connections (keep-alive). This eliminates the overhead of TCP and TLS handshakes for each request, significantly reducing latency for high-frequency trading.
| Setting | Value |
|---|---|
| Idle timeout | 90 seconds |
| Max requests per connection | 1000 |
Ping Endpoint
Use the /ping endpoint to keep connections alive without sending actual requests.
Request
GET /pingResponse
pongcURL
curl -X GET 'https://fra.blocksprint.io/ping'Usage
Python
import requests
import threading
import time
session = requests.Session()
ENDPOINT = "https://fra.blocksprint.io/api/v1/YOUR_API_KEY"
# Keep-alive ping every 60 seconds
def keep_alive():
while True:
session.get("https://fra.blocksprint.io/ping")
time.sleep(60)
threading.Thread(target=keep_alive, daemon=True).start()
# Use the same session for all requests
response = session.post(ENDPOINT, json={
"jsonrpc": "2.0",
"id": 1,
"method": "sendTransaction",
"params": [encoded_tx]
})JavaScript (Node.js)
// npm install undici
import { Agent, fetch } from "undici";
// Create agent with keep-alive enabled (idle sockets kept for 85 s)
const agent = new Agent({
keepAliveTimeout: 85_000,
keepAliveMaxTimeout: 85_000,
connections: 10,
});
const ENDPOINT = "https://fra.blocksprint.io/api/v1/YOUR_API_KEY";
// Keep-alive ping every 60 seconds
setInterval(async () => {
await fetch("https://fra.blocksprint.io/ping", { dispatcher: agent });
}, 60000);
// Use the same agent for all requests
async function sendTransaction(encodedTx) {
const response = await fetch(ENDPOINT, {
method: "POST",
dispatcher: agent,
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "sendTransaction",
params: [encodedTx],
}),
});
return response.json();
}Rust
use reqwest::Client;
use std::time::Duration;
#[tokio::main]
async fn main() {
// Client with connection pooling (keep-alive by default)
let client = Client::builder()
.pool_idle_timeout(Duration::from_secs(90))
.pool_max_idle_per_host(10)
.build()
.unwrap();
let endpoint = "https://fra.blocksprint.io/api/v1/YOUR_API_KEY";
// Keep-alive ping task
let ping_client = client.clone();
tokio::spawn(async move {
loop {
let _ = ping_client
.get("https://fra.blocksprint.io/ping")
.send()
.await;
tokio::time::sleep(Duration::from_secs(60)).await;
}
});
// Use the same client for all requests
let response = client
.post(endpoint)
.json(&serde_json::json!({
"jsonrpc": "2.0",
"id": 1,
"method": "sendTransaction",
"params": [encoded_tx]
}))
.send()
.await
.unwrap();
}Benefits
| Without Keep-Alive | With Keep-Alive |
|---|---|
| TCP handshake (~1 RTT) | Reused connection |
| TLS handshake (~2 RTT) | Reused TLS session |
| ~50-150ms overhead | ~0ms overhead |
For high-frequency trading, this can mean the difference between landing a transaction and missing the slot.
Best Practices
Ping every 60 seconds
Stay well under the 90-second timeout by pinging periodically.
Reuse your HTTP client
Don't create new clients per request — reuse sessions/agents/clients to benefit from connection pooling.
Set appropriate pool size
Match your concurrency needs by configuring pool sizes (e.g., connections, pool_max_idle_per_host).
Handle reconnects gracefully
Be prepared for connections to close after 1000 requests and implement retry/reconnect logic.
Rate Limit
The /ping endpoint has no rate limit and does not count against your API quota.
