Boost Web Performance: Leveraging navigator.sendBeacon and Kafka for Efficient Data Transmission

This article explains how to improve front‑end data transfer using the browser's navigator.sendBeacon API and how to streamline back‑end processing with Go, Kafka, and ClickHouse to achieve higher performance and stability in feature‑heavy web applications.

Code Wrench
Code Wrench
Code Wrench
Boost Web Performance: Leveraging navigator.sendBeacon and Kafka for Efficient Data Transmission

Frontend Transmission Insight: Making Full Use of the Browser

When building feature‑heavy websites, developers often face bloated front‑end code and performance degradation. To address this, the article recommends minimizing payload size and using modern protocols like HTTP/3, then leveraging the browser's navigator.sendBeacon method, which sends data asynchronously and independently of the page lifecycle.

Example implementation:

function send(api, metric) {
    const body = JSON.stringify(metric);
    if (document.URL.startsWith("https://www.laiys.com")) {
        api = "https://analysis.laiys.com/api/v1/" + api;
    } else {
        api = "https://localanalysis.laiys.com/api/v1/" + api;
    }
    if (navigator.sendBeacon && navigator.sendBeacon(api, body)) {
        // sent successfully, no further action needed
    } else {
        // fallback to XHR if sendBeacon is unavailable or fails
        xhrsend(api, body);
    }
}

function xhrsend(api, body) {
    const xhr = createXHR();
    xhr.open("POST", api, true);
    xhr.setRequestHeader("Content-type", "application/json;charset=UTF-8");
    xhr.send(body);
}

function createXHR() {
    var XHR = [
        () => new XMLHttpRequest(),
        () => new ActiveXObject("Msxml2.XMLHTTP"),
        () => new ActiveXObject("Msxml3.XMLHTTP"),
        () => new ActiveXObject("Microsoft.XMLHTTP")
    ];
    var xhr = null;
    for (let i = 0; i < XHR.length; i++) {
        try {
            xhr = XHR[i]();
            break;
        } catch (e) {
            continue;
        }
    }
    return xhr;
}

The code first attempts to send data with navigator.sendBeacon; if unavailable or failed, it falls back to an XHR request, thus fully utilizing the browser's capabilities for efficient transmission.

Backend Interface Optimization: Let Specialists Do Their Job

High‑traffic back‑end APIs can become bottlenecks. The article suggests simplifying the API's responsibility to merely receiving messages, delegating storage and processing to specialized systems. While relational databases struggle with massive concurrency, the solution adopts ClickHouse for column‑ariented storage, Kafka as a message queue, and Go for the service implementation.

Key Go/Kafka client example:

package service

import (
    "context"
    "log"
    "github.com/segmentio/kafka-go"
    "github.com/spf13/viper"
)

type Client struct {
    host     string      // Kafka address
    instance *kafka.Conn // Kafka connection instance
}

// Connect connects to a Kafka broker
func (client *Client) Connect(topic string) {
    conn, err := kafka.DialLeader(context.Background(), "tcp", client.host, topic, 0)
    if err != nil {
        log.Println("failed to dial leader: " + err.Error())
    }
    client.instance = conn
}

type Producer struct {
    client *Client
}

// Send publishes a message to Kafka
func (producer Producer) Send(key string, value string) {
    msg := kafka.Message{Key: []byte(key), Value: []byte(value)}
    _, err := producer.client.instance.WriteMessages(msg)
    if err != nil {
        log.Println("reconn kafka error: " + err.Error())
        producer.client.Connect(viper.GetString("common.kafka.topic"))
        _, err1 := producer.client.instance.WriteMessages(msg)
        if err1 != nil {
            log.Println("failed to write message: " + err1.Error())
        }
    }
}

func NewClient(host string) *Client {
    return &Client{host: host}
}

func NewProducer() Producer {
    kafkaClient := NewClient(viper.GetString("common.kafka.addr"))
    kafkaClient.Connect(viper.GetString("common.kafka.topic"))
    return Producer{client: kafkaClient}
}

By routing incoming data to Kafka, the API avoids direct database writes, eliminating I/O blocking. ClickHouse handles large‑scale, real‑time queries, while Kafka decouples storage and processing, resulting in higher overall system performance and stability.

Conclusion: Optimization Mindset in Development

Effective development hinges on thoughtful decomposition of responsibilities. On the front end, leveraging navigator.sendBeacon improves transmission efficiency. On the back end, simplifying API duties, employing Kafka for asynchronous processing, and choosing ClickHouse for massive, real‑time analytics together address performance challenges and prevent project stagnation.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

BackendfrontendperformanceKafkaClickHousenavigator.sendBeacon
Code Wrench
Written by

Code Wrench

Focuses on code debugging, performance optimization, and real-world engineering, sharing efficient development tips and pitfall guides. We break down technical challenges in a down-to-earth style, helping you craft handy tools so every line of code becomes a problem‑solving weapon. 🔧💻

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.