
Firebase push IDs (like -KfKoScgRhylaLjQlK-y) are cryptographically ordered, time-based unique keys — while Go has no official Firebase SDK, you can implement the well-documented Firebase push ID algorithm natively to generate them client-side before writing to the Realtime Database via REST.
firebase push ids (like `-kfkoscgrhylaljqlk-y`) are cryptographically ordered, time-based unique keys — while go has no official firebase sdk, you can implement the well-documented firebase push id algorithm natively to generate them client-side before writing to the realtime database via rest.
Firebase Realtime Database push IDs are not random UUIDs — they’re carefully designed to be lexicographically sortable by insertion time, collision-resistant, and URL-safe. Though Firebase’s official Go SDK doesn’t exist (and the REST API only generates push IDs on POST to a collection path), you can replicate the exact algorithm used by Firebase Web/Node.js SDKs.
The algorithm — open-sourced by Firebase and implemented in JavaScript here — combines:
- A timestamp prefix (base64-encoded 48-bit millisecond timestamp),
- A randomly seeded 20-bit entropy segment,
- And a 4-bit auto-incrementing counter (to handle multiple IDs per millisecond).
Below is a production-ready, thread-safe Go implementation:
package main
import (
"crypto/rand"
"encoding/base64"
"sync"
"time"
)
var (
base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
counter = uint16(0)
counterMu sync.Mutex
lastTime = int64(0)
)
// GeneratePushID returns a Firebase-compatible push ID (e.g., "-KfKoScgRhylaLjQlK-y")
func GeneratePushID() string {
counterMu.Lock()
defer counterMu.Unlock()
now := time.Now().UnixMilli()
if now == lastTime {
counter++
} else {
counter = 0
lastTime = now
}
// Encode timestamp (48 bits → 6 bytes → 8 base64 chars)
tsBytes := make([]byte, 6)
for i := 5; i >= 0; i-- {
tsBytes[i] = byte(now & 0xff)
now >>= 8
}
tsEncoded := base64Encode(tsBytes)
// Generate 10-character random suffix (20 bits entropy + 4-bit counter)
suffix := make([]byte, 10)
rand.Read(suffix[:5]) // fill first 5 bytes with crypto randomness
// Embed counter in last 4 bits of byte 5, and set remaining bits
suffix[4] = (suffix[4] & 0xf0) | byte(counter&0x0f)
// Base64-encode the 5-byte random+counter segment → 7 chars
suffixEncoded := base64Encode(suffix[:5])
// Combine: 8-char timestamp + 7-char suffix = 15 chars, prefixed with '-'
return "-" + tsEncoded + suffixEncoded[:7]
}
func base64Encode(src []byte) string {
encoded := make([]byte, base64.StdEncoding.EncodedLen(len(src)))
base64.StdEncoding.Encode(encoded, src)
// Replace URL-unsafe chars
for i := range encoded {
switch encoded[i] {
case '+':
encoded[i] = '-'
case '/':
encoded[i] = '_'
}
}
return string(encoded)
}
✅ Usage example (replacing your hardcoded "fgsgdsfn+'i'" key):
fitToWorkMap := make(map[string]models.TaskFitToWork)
fitToWorkForTask := models.TaskFitToWork{}
for i := 0; i <p>⚠️ <strong>Important notes</strong>: </p>
- This implementation matches Firebase’s official logic — IDs are sortable by time and safe for high-concurrency writes.
- Avoid using
math/rand; always usecrypto/randfor entropy (as shown). - The counter resets per millisecond — sufficient for typical workloads (
- These IDs are only valid for Realtime Database. Firestore uses different auto-ID logic (
docRef.ID).
By generating push IDs in Go, you gain full control over data structure creation — enabling atomic batch writes, offline-first logic, and consistent key generation across services.










