Documentation Index Fetch the complete documentation index at: https://mintlify.com/questdb/questdb/llms.txt
Use this file to discover all available pages before exploring further.
The QuestDB Go client provides an idiomatic Go API for ingesting data using the InfluxDB Line Protocol.
Installation
go get github.com/questdb/go-questdb-client/v3
Quick start
package main
import (
" context "
" fmt "
" time "
qdb " github.com/questdb/go-questdb-client/v3 "
)
func main () {
ctx := context . Background ()
sender , err := qdb . LineSenderFromConf ( ctx , "http::addr=localhost:9000" )
if err != nil {
panic ( err )
}
defer sender . Close ( ctx )
err = sender .
Table ( "trades" ).
Symbol ( "symbol" , "ETH-USD" ).
Symbol ( "side" , "sell" ).
Float64Column ( "price" , 2615.54 ).
Float64Column ( "amount" , 0.00044 ).
AtNow ( ctx )
if err != nil {
panic ( err )
}
err = sender . Flush ( ctx )
if err != nil {
panic ( err )
}
}
Configuration
sender , err := qdb . LineSenderFromConf (
ctx ,
"http::addr=localhost:9000;username=admin;password=quest;" ,
)
// Or TCP
tcpSender , err := qdb . LineSenderFromConf (
ctx ,
"tcp::addr=localhost:9009;username=admin;token=your-token;" ,
)
Connection string options
Server address (host:port)
Authentication password (HTTP)
Authentication token (TCP)
Data types
err = sender .
Table ( "sensors" ).
Symbol ( "location" , "warehouse-1" ). // Symbol
Int64Column ( "sensor_id" , 12345 ). // Int64
Float64Column ( "temperature" , 23.5 ). // Float64
StringColumn ( "status" , "active" ). // String
BoolColumn ( "is_online" , true ). // Boolean
TimestampColumn ( "measured_at" , time . Now ()). // Timestamp
AtNow ( ctx )
Batching
ctx := context . Background ()
sender , err := qdb . LineSenderFromConf ( ctx , "http::addr=localhost:9000" )
if err != nil {
panic ( err )
}
defer sender . Close ( ctx )
// Send 1000 rows
for i := 0 ; i < 1000 ; i ++ {
err = sender .
Table ( "metrics" ).
Symbol ( "host" , fmt . Sprintf ( "server- %d " , i % 10 )).
Float64Column ( "cpu" , float64 ( i % 100 )).
Float64Column ( "memory" , float64 (( i * 2 ) % 100 )).
AtNow ( ctx )
if err != nil {
panic ( err )
}
}
err = sender . Flush ( ctx )
if err != nil {
panic ( err )
}
Auto-flush
sender , err := qdb . LineSenderFromConf (
ctx ,
"http::addr=localhost:9000;auto_flush=on;auto_flush_rows=1000;" ,
)
if err != nil {
panic ( err )
}
defer sender . Close ( ctx )
// Automatically flushes after 1000 rows
for i := 0 ; i < 5000 ; i ++ {
err = sender .
Table ( "events" ).
Symbol ( "type" , "page_view" ).
StringColumn ( "url" , fmt . Sprintf ( "/page- %d " , i )).
AtNow ( ctx )
if err != nil {
panic ( err )
}
}
// Flush remaining rows
err = sender . Flush ( ctx )
if err != nil {
panic ( err )
}
Error handling
ctx := context . Background ()
sender , err := qdb . LineSenderFromConf ( ctx , "http::addr=localhost:9000" )
if err != nil {
log . Fatalf ( "Failed to create sender: %v " , err )
}
defer sender . Close ( ctx )
err = sender .
Table ( "trades" ).
Symbol ( "symbol" , "BTC-USD" ).
Float64Column ( "price" , 50000.0 ).
AtNow ( ctx )
if err != nil {
log . Printf ( "Failed to write row: %v " , err )
return
}
err = sender . Flush ( ctx )
if err != nil {
log . Printf ( "Failed to flush: %v " , err )
return
}
Context cancellation
ctx , cancel := context . WithTimeout ( context . Background (), 5 * time . Second )
defer cancel ()
sender , err := qdb . LineSenderFromConf ( ctx , "http::addr=localhost:9000" )
if err != nil {
panic ( err )
}
defer sender . Close ( ctx )
err = sender .
Table ( "metrics" ).
Symbol ( "host" , "server-1" ).
Float64Column ( "cpu" , 45.2 ).
AtNow ( ctx )
if err != nil {
if ctx . Err () == context . DeadlineExceeded {
log . Println ( "Operation timed out" )
}
panic ( err )
}
err = sender . Flush ( ctx )
if err != nil {
panic ( err )
}
Goroutine safety
The sender is not goroutine-safe. Create separate senders for concurrent goroutines.
func worker ( ctx context . Context , id int , wg * sync . WaitGroup ) {
defer wg . Done ()
sender , err := qdb . LineSenderFromConf ( ctx , "http::addr=localhost:9000" )
if err != nil {
panic ( err )
}
defer sender . Close ( ctx )
for i := 0 ; i < 100 ; i ++ {
err = sender .
Table ( "worker_metrics" ).
Symbol ( "worker_id" , fmt . Sprintf ( "worker- %d " , id )).
Int64Column ( "iteration" , int64 ( i )).
AtNow ( ctx )
if err != nil {
panic ( err )
}
}
err = sender . Flush ( ctx )
if err != nil {
panic ( err )
}
}
func main () {
ctx := context . Background ()
var wg sync . WaitGroup
// Launch 10 workers, each with its own sender
for i := 0 ; i < 10 ; i ++ {
wg . Add ( 1 )
go worker ( ctx , i , & wg )
}
wg . Wait ()
}
Use HTTP protocol with auto-flush for optimal throughput.
Enable auto-flush : Let the client handle batching
Use HTTP protocol : Better performance for most use cases
One sender per goroutine : Avoid mutex overhead
Context timeouts : Prevent hanging connections
Next steps
ILP Reference Learn about the protocol