Geode documentation tagged with QUIC Protocol. QUIC (Quick UDP Internet Connections) is a modern transport protocol that provides the reliability of TCP with the performance of UDP, featuring built-in encryption, multiplexing, and connection migration.

Introduction to QUIC

QUIC is a transport layer protocol initially developed by Google and subsequently standardized by the IETF in RFC 9000 (2021). Unlike TCP, which operates over raw IP and requires a separate TLS handshake for encryption, QUIC runs over UDP and integrates encryption directly into the protocol using TLS 1.3. This design eliminates head-of-line blocking, reduces connection establishment latency, and provides robust connection migration for mobile and multi-homed devices.

For database connections, QUIC offers significant advantages over traditional TCP/TLS stacks. The protocol’s stream multiplexing allows multiple concurrent queries over a single connection without one slow query blocking others. Connection migration means mobile applications maintain database connections when switching between WiFi and cellular networks. The 0-RTT resumption feature enables reconnecting clients to send application data immediately without waiting for handshake completion, critical for latency-sensitive applications.

Geode exclusively uses QUIC for client-server communication, running on the standard port 3141. There is no TCP fallback—all connections require QUIC support. This bold design choice reflects confidence in QUIC’s maturity and recognition that modern networks and client libraries have excellent QUIC support. By eliminating TCP compatibility layers, Geode achieves a simpler, more efficient wire protocol with guaranteed encryption and superior performance characteristics.

Key Concepts

UDP-Based Transport

QUIC runs over UDP rather than TCP:

  • User Datagram Protocol: Connectionless, unreliable packet delivery
  • QUIC Reliability Layer: Implements reliable, ordered delivery on top of UDP
  • Congestion Control: Advanced congestion algorithms (Cubic, BBR)
  • Packet Loss Recovery: Fast retransmission and forward error correction

Stream Multiplexing

QUIC supports multiple independent streams per connection:

  • Bidirectional Streams: Both endpoints can send and receive
  • Unidirectional Streams: Data flows in only one direction
  • Stream IDs: Unique identifier for each stream
  • No Head-of-Line Blocking: Packet loss on one stream doesn’t affect others

Integrated Encryption

TLS 1.3 is built into QUIC from the ground up:

  • Mandatory Encryption: All QUIC packets are encrypted
  • TLS 1.3 Handshake: Modern, efficient cryptographic handshake
  • 0-RTT Resumption: Resume previous connection without handshake latency
  • Forward Secrecy: Perfect forward secrecy for all connections

Connection Migration

QUIC connections can migrate across network paths:

  • Connection IDs: Persistent identifier independent of IP address/port
  • Path Validation: Verify new paths before migration
  • Mobile Scenarios: Seamless WiFi to cellular transitions
  • Multi-homed Hosts: Failover between network interfaces

1-RTT Connection Establishment

QUIC combines transport and encryption handshakes:

Client                                Server
   |                                     |
   | Initial (ClientHello)               |
   |------------------------------------>|
   |                                     |
   | <- Initial (ServerHello, Certificate, Finished)
   | <- Handshake (CRYPTO)              |
   |<------------------------------------|
   |                                     |
   | Handshake (Finished)                |
   | 1-RTT (Application Data)            |
   |------------------------------------>|

Compared to TCP + TLS (2-RTT minimum), QUIC achieves 1-RTT connection establishment, and 0-RTT for resumed connections.

How QUIC Works in Geode

Wire Protocol Architecture

Geode’s wire protocol leverages QUIC streams:

  1. Connection Establishment: Client initiates QUIC connection to port 3141
  2. Stream Allocation: Each query executes on a dedicated bidirectional stream
  3. Request/Response: Protobuf wire protocol messages flow over streams
  4. Concurrent Queries: Multiple queries execute in parallel using different streams
  5. Connection Pooling: Clients maintain persistent QUIC connections

Protobuf Messages Over QUIC

Each QUIC stream carries a request-response conversation using Protobuf messages:

  • ExecuteRequestExecutionResponse (schema + first page)
  • PullRequestExecutionResponse (subsequent pages)

Stream Management

Geode uses QUIC streams efficiently:

  • Query Streams: One bidirectional stream per query
  • Control Stream: Stream 0 reserved for connection control messages
  • CDC Streams: Unidirectional server-to-client streams for change events
  • Multiplexing: Up to 100 concurrent streams per connection by default

Connection Migration Support

Geode fully supports QUIC connection migration:

import geode_client

# Client maintains connection during network changes
client = geode_client.open_database('quic://db.example.com:3141')
async with client.connection() as conn:
    # Execute query on WiFi
    result, _ = await conn.query("MATCH (n:Person) RETURN count(n)")

    # User moves from WiFi to cellular - connection migrates automatically
    # Network stack detects new path, validates it, and migrates connection

    # Subsequent query uses migrated connection without interruption
    result, _ = await conn.query("MATCH (n:Product) RETURN count(n)")

0-RTT Resumption

Geode supports 0-RTT for repeat connections:

# First connection: 1-RTT handshake
client = geode_client.open_database('quic://db.example.com:3141')
async with client.connection() as conn:
    result, _ = await conn.query("MATCH (n) RETURN count(n)")
# Server sends session ticket for resumption

# Second connection within ticket lifetime: 0-RTT
client = geode_client.open_database('quic://db.example.com:3141')
async with client.connection() as conn:
    # Query sent in first packet, no handshake wait
    result, _ = await conn.query("MATCH (n) RETURN count(n)")

Use Cases

Low-Latency Query Execution

import geode_client
import asyncio

async def measure_query_latency():
    """Measure end-to-end query latency with QUIC."""
    client = geode_client.open_database('quic://localhost:3141')
    async with client.connection() as conn:
        for i in range(100):
            start = asyncio.get_event_loop().time()

            result, _ = await conn.query(
                "MATCH (n:Person {id: $id}) RETURN n.name",
                {"id": i}
            )
            row = result.rows[0] if result.rows else None

            latency = (asyncio.get_event_loop().time() - start) * 1000
            print(f"Query {i}: {latency:.2f}ms")

# Typical latencies with QUIC:
# Local: 0.5-2ms
# Same datacenter: 2-5ms
# Cross-region: 50-150ms

Concurrent Query Execution

async def concurrent_queries():
    """Execute multiple queries in parallel over QUIC streams."""
    client = geode_client.open_database('quic://localhost:3141')
    async with client.connection() as conn:
        # All queries use the same QUIC connection but different streams
        results = await asyncio.gather(
            conn.execute("MATCH (p:Person) RETURN count(p)"),
            conn.execute("MATCH (c:Company) RETURN count(c)"),
            conn.execute("MATCH (p:Product) RETURN count(p)"),
            conn.execute("MATCH ()-[r]->() RETURN count(r)")
        )

        for i, result in enumerate(results):
            row = result.rows[0] if result.rows else None
            print(f"Query {i}: {row[0]} entities")

# QUIC multiplexing allows all queries to execute concurrently
# without head-of-line blocking

Mobile Application Resilience

import asyncio
from geode_client import GeodeConnectionError, open_database

class MobileClient:
    """Database client that retries on transient network loss."""

    def __init__(self, url: str):
        self.client = open_database(url)

    async def query(self, gql: str):
        """Execute query with a simple reconnect loop."""
        while True:
            try:
                async with self.client.connection() as conn:
                    result, _ = await conn.query(gql)
                    return result.rows
            except GeodeConnectionError:
                await asyncio.sleep(0.5)

# Usage in mobile app
client = MobileClient('quic://db.example.com:3141')

# Works seamlessly across WiFi/cellular transitions
results = await client.query("MATCH (n:Person) RETURN n.name LIMIT 10")

WAN Optimization

from geode_client import ConnectionPool

async def wan_optimized_queries():
    """Optimize queries over high-latency WAN links."""
    pool = ConnectionPool(host="remote-db.example.com", port=3141, max_size=20)
    async with pool:
        async def run_query(i: int):
            async with pool.acquire() as conn:
                result, _ = await conn.query(
                    "MATCH (n:Person {id: $id}) RETURN n",
                    {"id": i},
                )
                return result.rows

        results = await asyncio.gather(*(run_query(i) for i in range(50)))

Best Practices

Connection Management

  1. Connection Pooling: Reuse QUIC connections for multiple queries
  2. Connection Limits: Configure appropriate max streams per connection
  3. Idle Timeout: Set reasonable idle timeout for connection reuse
  4. Graceful Shutdown: Close streams and connections cleanly

Performance Tuning

  1. Stream Concurrency: Adjust max concurrent streams for workload
  2. Congestion Control: Choose appropriate algorithm (Cubic vs BBR)
  3. 0-RTT Enablement: Enable for repeat connections to reduce latency
  4. Buffer Sizes: Tune send/receive buffers for throughput

Security Configuration

  1. Certificate Validation: Always validate server certificates
  2. TLS 1.3 Only: Ensure only TLS 1.3 is enabled
  3. Cipher Suites: Use strong, modern cipher suites
  4. Session Tickets: Manage session ticket security appropriately

Network Considerations

  1. Firewall Rules: Ensure UDP port 3141 is open
  2. NAT Traversal: QUIC handles NAT better than TCP
  3. Path MTU: QUIC performs automatic path MTU discovery
  4. QoS: Configure appropriate QoS for UDP traffic

Performance Considerations

Latency Improvements

QUIC reduces latency through:

  • 1-RTT Handshake: 50% faster than TCP+TLS
  • 0-RTT Resumption: Eliminates handshake for repeat connections
  • No Head-of-Line Blocking: Packet loss doesn’t block other streams
  • Fast Retransmission: Rapid packet loss recovery

Typical improvements over TCP+TLS:

  • First connection: 20-30% faster
  • Resumed connection: 50-70% faster
  • Lossy networks: 2-5x faster query execution

Throughput Characteristics

QUIC throughput is excellent:

  • Single Stream: Comparable to TCP (within 5%)
  • Multiple Streams: 50-200% better than TCP due to multiplexing
  • Lossy Links: 100-300% better than TCP
  • High-Latency Links: BBR congestion control excels

Resource Usage

QUIC resource consumption is modest:

  • Memory: ~100KB per connection (vs ~50KB for TCP+TLS)
  • CPU: ~10% higher than TCP+TLS for encryption/decryption
  • Bandwidth: 1-2% overhead from QUIC headers
  • Ports: Single UDP port vs separate TCP ports

Troubleshooting

Connection Failures

Symptom: Unable to establish QUIC connection

Solutions:

  • Verify UDP port 3141 is reachable
  • Check firewall rules allow UDP traffic
  • Ensure client supports QUIC (all official clients do)
  • Verify server certificate is valid
  • Check for NAT or middlebox interference

High Latency

Symptom: Queries slower than expected

Solutions:

  • Check network latency with ping/traceroute
  • Verify no packet loss on link
  • Tune congestion control algorithm
  • Increase max concurrent streams
  • Enable 0-RTT for repeat connections

Stream Errors

Symptom: Stream reset or connection closed unexpectedly

Solutions:

  • Check for max streams exceeded
  • Verify proper stream lifecycle management
  • Review server logs for errors
  • Ensure queries complete before closing streams
  • Monitor connection idle timeout

Connection Migration Issues

Symptom: Connection fails during network transition

Solutions:

  • Verify connection migration is enabled
  • Check path validation succeeds
  • Review NAT rebinding behavior
  • Ensure sufficient timeout for migration
  • Monitor connection ID management

Further Reading


Related Articles