High-Performance Device Profile Generation API
Device profile generation is a deceptively complex problem. A realistic device profile is not just a random model name and OS version — it is a coherent constellation of hundreds of interdependent hardware and software attributes: build fingerprint, kernel version, carrier-specific APN configuration, hardware sensor array, screen density, GPU renderer string, and a cryptographically unique ECDSA keypair. Every attribute must be plausible, internally consistent, and reproducible.
I built a Go API that generates these profiles at sub-millisecond speed, with zero external dependencies, across global markets and an extensive device catalog, with deterministic generation — the same seed always produces the same device.
Why Go?
The language choice was driven by three requirements: performance, deployment simplicity, and cryptographic capability. Go's standard library includes a complete suite of cryptographic primitives (crypto/aes, crypto/hmac, crypto/ecdsa, crypto/elliptic), high-performance HTTP routing, and compiles to a single static binary with no runtime dependency.
Throughput (devices/second)
Binary Deployment
Go compiles to a single static binary (~8MB). No runtime to install, no package manager to run, no dependency conflicts. Docker image is 12MB (scratch base). Node.js equivalent: 280MB with node_modules.
The Deterministic Randomness Problem
Generating realistic device profiles requires randomness — but randomness that can be replayed. If a test run generates device profile A and then needs to reproduce it for debugging, pure crypto/rand randomness is useless: it cannot be seeded and replayed.
The solution is a Deterministic Random Bit Generator (DRBG) — a NIST-specified construct that produces cryptographically strong pseudorandom output from a seed, reproducibly.
func NewDRBG(seed []byte) *DRBG {
// HKDF expands the seed into a 32-byte key + 16-byte IV
hkdf := hkdf.New(sha256.New, seed, salt, info)
io.ReadFull(hkdf, key) // first 32 bytes → AES key
io.ReadFull(hkdf, iv) // next 16 bytes → CTR counter
// AES-CTR stream cipher: deterministic, high-throughput
return &DRBG{stream: cipher.NewCTR(block, iv)}
}
// Every call to Read() produces the same bytes for the same seed
func (d *DRBG) Intn(n int) int { ... }
Using AES-CTR as the underlying stream cipher means the DRBG is as fast as AES hardware acceleration (available on all modern CPUs via AES-NI) while producing output indistinguishable from true randomness. HKDF-SHA256 ensures the seed is safely expanded even if the seed is low-entropy (e.g., a short string).
Internal Consistency: The Hard Problem
Generating a random model name is trivial. Generating a coherent device profile is not. The following attributes are all interdependent in a real device:
- Build fingerprint: Encodes manufacturer, model, Android version, build date, and security patch level. All must match the device model's actual release history
- Screen density bucket: A device with a 6.5" screen at 1080×2400 resolution has a specific DPI range. The generated value must fall within that range
- Kernel version string: Format varies by manufacturer — Samsung uses one convention, Google Pixel another, OnePlus another
- Carrier + APN configuration: Devices in different regions use different carrier APN settings. Country, carrier, and APN must form a valid, regionally consistent triple
- OpenGL ES version and GPU renderer: Tied to the SoC family (Snapdragon 888 → Adreno 660, Dimensity 9000 → Mali-G710)
The generation engine resolves these dependencies by selecting from embedded JSON catalogs: phones.json, android_versions.json, carriers.json, apns.json, gpus.json. Lookup indexes are built at startup for O(1) access during generation. The DRBG selects indices into these catalogs — so all randomness is bounded by real-world data.
API Surface
| Method | Path | Description |
|---|---|---|
| GET | /device | Generate a single device profile (random seed) |
| GET | /device?seed=<value> | Generate a deterministic device from an explicit seed |
| POST | /devices/batch | Generate 1–100 devices concurrently (goroutine fan-out) |
| GET | /device?region=us&category=flagship | Filter by region + device category |
| GET | /health | Health check — returns 200 OK for orchestration |
Batch Processing: Goroutine Fan-Out
The batch endpoint uses a goroutine fan-out pattern — all N devices are generated concurrently, then collected via a channel. Because each device generation is CPU-bound and stateless, Go's scheduler distributes work across all available cores with zero synchronization overhead (each goroutine has its own DRBG instance seeded from an atomic counter).
func generateBatch(n int) []Device {
ch := make(chan Device, n)
var wg sync.WaitGroup
for i := 0; i < n; i++ {
wg.Add(1)
go func(seed int64) {
defer wg.Done()
ch <- generateOne(newDRBG(seed))
}(atomic.AddInt64(&counter, 1))
}
wg.Wait()
close(ch)
// collect results...
}
ECDSA Keypair Generation per Device
Each device profile includes a unique ECDSA P-256 keypair. The private key is derived deterministically from the device seed, making the keypair reproducible without storage. The public key is embedded in the profile as the device's cryptographic identity. Key generation uses Go's standard crypto/elliptic package — no external cryptographic library needed.
go mod tidy produces an empty go.sum.
Deployment
The service ships as a Docker image built on scratch (the empty base image). The final image is ~12MB: the statically linked Go binary plus the embedded JSON catalogs. No shell, no package manager, no libc — a minimal attack surface by default.
FROM golang:1.21-alpine AS builder
RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o /app .
FROM scratch
COPY --from=builder /app /app
EXPOSE 8080
ENTRYPOINT ["/app"]