Go is the language of choice for high-performance backend services. Its goroutine-based concurrency model, static binary output, and compile-time type safety make it ideal for astrology microservices that must handle thousands of birth chart requests with low latency and zero runtime surprises.
In this tutorial you will build a production-ready Go service that integrates Vedika API — the only B2B astrology API with an AI-powered natural language engine, 140+ endpoints, and Swiss Ephemeris astronomical precision. By the end you will have a working CLI tool and an HTTP REST wrapper, both using idiomatic Go patterns.
What You'll Build: A Go module with typed structs for birth chart requests and responses, an http.Client wrapper around Vedika API, concurrent multi-query execution via goroutines, a CLI tool for quick lookups, and an HTTP server that exposes astrology endpoints to other services.
Why Go for Astrology Services?
Goroutine Concurrency
Fan out birth chart, dasha, transit, and compatibility queries simultaneously. Collect all results in the time of the slowest single call.
Static Binary
Deploy a single binary with zero runtime dependencies. No Node, no Python, no JVM. Perfect for containers and bare-metal servers.
Compile-Time Safety
Typed structs catch JSON schema mismatches at build time, not in production at 3 AM when a user gets a wrong prediction.
Low Memory Footprint
Go services typically use 10-30 MB RAM versus 200-500 MB for equivalent Node.js services. Critical when running astrology workers at scale.
Prerequisites
- Go 1.21 or later installed (go.dev/dl)
- A Vedika API key — get yours here
- Basic familiarity with Go structs, interfaces, and goroutines
- cURL or any REST client to verify API calls
Step 1: Initialize the Go Module
Create a new directory and initialize your module:
mkdir vedika-go-client
cd vedika-go-client
go mod init github.com/yourusername/vedika-go-client
Your go.mod file will look like this. The standard library covers everything we need — no third-party HTTP or JSON libraries required:
module github.com/yourusername/vedika-go-client
go 1.21
Step 2: Define Typed Structs
Create types.go with structs that mirror Vedika API's request and response schemas. Proper typing eliminates entire classes of runtime errors:
package main
type BirthDetails struct {
Datetime string `json:"datetime"`
Latitude float64 `json:"latitude"`
Longitude float64 `json:"longitude"`
Timezone string `json:"timezone"`
}
type AstrologyQueryRequest struct {
Question string `json:"question"`
BirthDetails BirthDetails `json:"birthDetails"`
Language string `json:"language,omitempty"`
System string `json:"system,omitempty"`
}
type VedikaQueryResponse struct {
Answer string `json:"answer"`
Tokens int `json:"tokens"`
System string `json:"system"`
CachedResult bool `json:"cachedResult"`
}
type BirthChartRequest struct {
Datetime string `json:"datetime"`
Latitude float64 `json:"latitude"`
Longitude float64 `json:"longitude"`
Timezone string `json:"timezone"`
Ayanamsa string `json:"ayanamsa,omitempty"`
}
type PlanetPosition struct {
Name string `json:"name"`
Sign string `json:"sign"`
Degree float64 `json:"degree"`
House int `json:"house"`
Retrograde bool `json:"retrograde"`
Dignity string `json:"dignity"`
}
type BirthChartResponse struct {
Ascendant string `json:"ascendant"`
MoonSign string `json:"moonSign"`
SunSign string `json:"sunSign"`
Planets []PlanetPosition `json:"planets"`
ActiveYogas []string `json:"activeYogas"`
CurrentDasha struct {
Mahadasha string `json:"mahadasha"`
Antardasha string `json:"antardasha"`
EndsAt string `json:"endsAt"`
} `json:"currentDasha"`
}
type APIError struct {
StatusCode int
Message string
}
func (e *APIError) Error() string {
return fmt.Sprintf("vedika api error %d: %s", e.StatusCode, e.Message)
}
Step 3: Build the API Client
Create client.go — a reusable client with a configured http.Client, base URL, and API key. This pattern makes testing and mocking straightforward:
package main
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"time"
)
const (
defaultBaseURL = "https://api.vedika.io"
defaultTimeout = 30 * time.Second
)
type VedikaClient struct {
apiKey string
baseURL string
httpClient *http.Client
}
func NewVedikaClient(apiKey string) *VedikaClient {
return &VedikaClient{
apiKey: apiKey,
baseURL: defaultBaseURL,
httpClient: &http.Client{
Timeout: defaultTimeout,
},
}
}
func (c *VedikaClient) post(ctx context.Context, path string, body, dest interface{}) error {
payload, err := json.Marshal(body)
if err != nil {
return fmt.Errorf("marshal request: %w", err)
}
req, err := http.NewRequestWithContext(
ctx,
http.MethodPost,
c.baseURL+path,
bytes.NewReader(payload),
)
if err != nil {
return fmt.Errorf("create request: %w", err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+c.apiKey)
resp, err := c.httpClient.Do(req)
if err != nil {
return fmt.Errorf("execute request: %w", err)
}
defer resp.Body.Close()
bodyBytes, _ := io.ReadAll(resp.Body)
if resp.StatusCode >= 400 {
return &APIError{
StatusCode: resp.StatusCode,
Message: string(bodyBytes),
}
}
if err := json.Unmarshal(bodyBytes, dest); err != nil {
return fmt.Errorf("decode response: %w", err)
}
return nil
}
func (c *VedikaClient) QueryAI(ctx context.Context, req AstrologyQueryRequest) (*VedikaQueryResponse, error) {
var result VedikaQueryResponse
if err := c.post(ctx, "/api/v1/astrology/query", req, &result); err != nil {
return nil, err
}
return &result, nil
}
func (c *VedikaClient) GetBirthChart(ctx context.Context, req BirthChartRequest) (*BirthChartResponse, error) {
var result BirthChartResponse
if err := c.post(ctx, "/v2/astrology/birth-chart", req, &result); err != nil {
return nil, err
}
return &result, nil
}
Step 4: Concurrent Queries with Goroutines
Go's goroutines let you fan out multiple Vedika API calls in parallel. Instead of waiting sequentially for birth chart, dasha periods, and transits (which could take 3× the latency), you get all three in the time of the slowest single call:
package main
import (
"context"
"sync"
)
type AstrologyProfile struct {
BirthChart *BirthChartResponse
CareerQuery *VedikaQueryResponse
LoveQuery *VedikaQueryResponse
Errors []error
}
func FetchProfile(ctx context.Context, client *VedikaClient, bd BirthDetails) AstrologyProfile {
var (
wg sync.WaitGroup
mu sync.Mutex
profile AstrologyProfile
)
addErr := func(err error) {
mu.Lock()
profile.Errors = append(profile.Errors, err)
mu.Unlock()
}
wg.Add(1)
go func() {
defer wg.Done()
chart, err := client.GetBirthChart(ctx, BirthChartRequest{
Datetime: bd.Datetime,
Latitude: bd.Latitude,
Longitude: bd.Longitude,
Timezone: bd.Timezone,
})
if err != nil {
addErr(err)
return
}
mu.Lock()
profile.BirthChart = chart
mu.Unlock()
}()
wg.Add(1)
go func() {
defer wg.Done()
resp, err := client.QueryAI(ctx, AstrologyQueryRequest{
Question: "What are my career prospects for 2026?",
BirthDetails: bd,
})
if err != nil {
addErr(err)
return
}
mu.Lock()
profile.CareerQuery = resp
mu.Unlock()
}()
wg.Add(1)
go func() {
defer wg.Done()
resp, err := client.QueryAI(ctx, AstrologyQueryRequest{
Question: "What does my 7th house indicate about marriage timing?",
BirthDetails: bd,
})
if err != nil {
addErr(err)
return
}
mu.Lock()
profile.LoveQuery = resp
mu.Unlock()
}()
wg.Wait()
return profile
}
Step 5: Build a CLI Tool
Create main.go with a CLI interface using standard library flags. This lets astrologers or developers query Vedika API from the terminal without writing any code:
package main
import (
"context"
"flag"
"fmt"
"log"
"os"
"time"
)
func main() {
var (
apiKey = flag.String("key", "", "Vedika API key (or set VEDIKA_API_KEY env var)")
datetime = flag.String("datetime", "", "Birth datetime (ISO 8601, e.g. 1990-06-15T14:30:00+05:30)")
lat = flag.Float64("lat", 0, "Birth latitude (decimal degrees)")
lon = flag.Float64("lon", 0, "Birth longitude (decimal degrees)")
tz = flag.String("tz", "+05:30", "Timezone offset (default: +05:30 IST)")
question = flag.String("q", "", "Question to ask (AI natural language mode)")
concurrent = flag.Bool("concurrent", false, "Fetch full profile concurrently")
)
flag.Parse()
key := *apiKey
if key == "" {
key = os.Getenv("VEDIKA_API_KEY")
}
if key == "" {
log.Fatal("API key required: use -key flag or VEDIKA_API_KEY env var")
}
if *datetime == "" || *lat == 0 || *lon == 0 {
log.Fatal("Birth details required: -datetime, -lat, -lon")
}
client := NewVedikaClient(key)
ctx, cancel := context.WithTimeout(context.Background(), 45*time.Second)
defer cancel()
bd := BirthDetails{
Datetime: *datetime,
Latitude: *lat,
Longitude: *lon,
Timezone: *tz,
}
if *concurrent {
fmt.Println("Fetching full astrological profile (concurrent)...")
profile := FetchProfile(ctx, client, bd)
if profile.BirthChart != nil {
fmt.Printf("\n=== Birth Chart ===\nAscendant: %s | Moon: %s | Sun: %s\n",
profile.BirthChart.Ascendant,
profile.BirthChart.MoonSign,
profile.BirthChart.SunSign,
)
fmt.Printf("Active Yogas: %v\n", profile.BirthChart.ActiveYogas)
fmt.Printf("Current Dasha: %s / %s (ends %s)\n",
profile.BirthChart.CurrentDasha.Mahadasha,
profile.BirthChart.CurrentDasha.Antardasha,
profile.BirthChart.CurrentDasha.EndsAt,
)
}
if profile.CareerQuery != nil {
fmt.Printf("\n=== Career Prediction ===\n%s\n", profile.CareerQuery.Answer)
}
if profile.LoveQuery != nil {
fmt.Printf("\n=== Relationship Prediction ===\n%s\n", profile.LoveQuery.Answer)
}
for _, err := range profile.Errors {
fmt.Fprintf(os.Stderr, "warning: %v\n", err)
}
return
}
if *question != "" {
resp, err := client.QueryAI(ctx, AstrologyQueryRequest{
Question: *question,
BirthDetails: bd,
})
if err != nil {
log.Fatalf("AI query failed: %v", err)
}
fmt.Println(resp.Answer)
return
}
chart, err := client.GetBirthChart(ctx, BirthChartRequest{
Datetime: bd.Datetime,
Latitude: bd.Latitude,
Longitude: bd.Longitude,
Timezone: bd.Timezone,
})
if err != nil {
log.Fatalf("Birth chart failed: %v", err)
}
fmt.Printf("Ascendant: %s\nMoon Sign: %s\nSun Sign: %s\n",
chart.Ascendant, chart.MoonSign, chart.SunSign)
fmt.Printf("Planets:\n")
for _, p := range chart.Planets {
retroStr := ""
if p.Retrograde {
retroStr = " (R)"
}
fmt.Printf(" %-10s %s%s, House %d, %.2f°, %s\n",
p.Name, p.Sign, retroStr, p.House, p.Degree, p.Dignity)
}
}
Running the CLI
go build -o vedika-cli .
VEDIKA_API_KEY=vk_live_xxx ./vedika-cli \
-datetime "1990-06-15T14:30:00+05:30" \
-lat 18.9388 -lon 72.8354 \
-q "What does my current Mahadasha indicate for business?"
VEDIKA_API_KEY=vk_live_xxx ./vedika-cli \
-datetime "1990-06-15T14:30:00+05:30" \
-lat 18.9388 -lon 72.8354
VEDIKA_API_KEY=vk_live_xxx ./vedika-cli \
-datetime "1990-06-15T14:30:00+05:30" \
-lat 18.9388 -lon 72.8354 \
-concurrent
Step 6: Build an HTTP REST Wrapper
Expose Vedika API to your internal services through a typed Go HTTP server. This pattern is common in microservice architectures where you want a single access point with auth, logging, and retry logic:
package main
import (
"encoding/json"
"log"
"net/http"
"os"
)
func writeJSON(w http.ResponseWriter, status int, v interface{}) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
json.NewEncoder(w).Encode(v)
}
func startServer() {
client := NewVedikaClient(os.Getenv("VEDIKA_API_KEY"))
http.HandleFunc("/chart", func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
writeJSON(w, http.StatusMethodNotAllowed, map[string]string{"error": "POST only"})
return
}
var req BirthChartRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
return
}
chart, err := client.GetBirthChart(r.Context(), req)
if err != nil {
writeJSON(w, http.StatusBadGateway, map[string]string{"error": err.Error()})
return
}
writeJSON(w, http.StatusOK, chart)
})
http.HandleFunc("/query", func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
writeJSON(w, http.StatusMethodNotAllowed, map[string]string{"error": "POST only"})
return
}
var req AstrologyQueryRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
return
}
resp, err := client.QueryAI(r.Context(), req)
if err != nil {
writeJSON(w, http.StatusBadGateway, map[string]string{"error": err.Error()})
return
}
writeJSON(w, http.StatusOK, resp)
})
http.HandleFunc("/profile", func(w http.ResponseWriter, r *http.Request) {
var bd BirthDetails
if err := json.NewDecoder(r.Body).Decode(&bd); err != nil {
writeJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
return
}
profile := FetchProfile(r.Context(), client, bd)
writeJSON(w, http.StatusOK, profile)
})
log.Println("Vedika Go wrapper listening on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
Testing the REST Wrapper
VEDIKA_API_KEY=vk_live_xxx go run .
curl -X POST http://localhost:8080/chart \
-H "Content-Type: application/json" \
-d '{
"datetime": "1990-06-15T14:30:00+05:30",
"latitude": 18.9388,
"longitude": 72.8354,
"timezone": "+05:30"
}'
curl -X POST http://localhost:8080/query \
-H "Content-Type: application/json" \
-d '{
"question": "What career path suits me best?",
"birthDetails": {
"datetime": "1990-06-15T14:30:00+05:30",
"latitude": 18.9388,
"longitude": 72.8354,
"timezone": "+05:30"
}
}'
Production Best Practices
Context-Based Timeouts
Always pass a context with a timeout to prevent goroutine leaks when Vedika API is slow or unavailable:
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
resp, err := client.QueryAI(ctx, req)
if errors.Is(err, context.DeadlineExceeded) {
log.Println("Vedika API timeout — check network or increase timeout")
}
Retry with Exponential Backoff
func withRetry(attempts int, fn func() error) error {
var err error
for i := 0; i < attempts; i++ {
if err = fn(); err == nil {
return nil
}
var apiErr *APIError
if errors.As(err, &apiErr) && apiErr.StatusCode == 429 {
wait := time.Duration(1<Sleep(wait)
continue
}
return err
}
return err
}
Environment-Based Configuration
export VEDIKA_API_KEY="vk_live_your_key_here"
Why Vedika API Beats Competitors for Go Services
140+ Endpoints
Birth charts, planetary positions, yogas, doshas, dashas, transits, panchang, numerology, Shadbala, and much more — all accessible from Go.
AI Natural Language
One endpoint handles any astrology question in plain English. No need to learn 140 calculation APIs individually.
Swiss Ephemeris Precision
Astronomical-grade planetary positions. Same engine used by professional astrology software worldwide.
30 Languages
Hindi, Tamil, Telugu, Gujarati, Bengali, Marathi, Kannada — and 23 more. Build for India's diversity from one API.
MCP Server
World's first astrology MCP server. AI agents can call Vedika natively — no custom integration needed.
Starts at $12/month
No per-endpoint pricing surprises. Wallet-based credits. Starter covers most Go microservice use cases.
Conclusion
Building a Go astrology service with Vedika API is clean and idiomatic. The key advantages:
- Static binary deployment:
go build produces a self-contained executable ready for any container or server
- Goroutine concurrency: Fan out multiple Vedika API calls with near-zero overhead compared to thread-based approaches
- Type safety: Struct definitions catch API schema mismatches at compile time, not in production
- No runtime dependencies: Pure standard library for HTTP and JSON — nothing to install on the target machine
- AI built-in: Natural language queries mean your Go service can answer any astrology question without implementing calculation logic
Next steps:
- Get your Vedika API key at vedika.io/signup
- Run
go mod init and paste the code above into your project
- Test with
go run . -concurrent -datetime "1990-06-15T14:30:00+05:30" -lat 18.9388 -lon 72.8354
- Add your business logic around the typed responses
- Deploy the single binary to Cloud Run, GKE, or any Linux server
For full endpoint documentation, sandbox testing, and code samples in 12 languages, visit our developer documentation.
About Vedika Intelligence: Vedika is the only B2B astrology API with an AI-powered chatbot and 140+ calculation endpoints, serving production apps worldwide. Built on Swiss Ephemeris for astronomical precision, supporting Vedic, Western, and KP astrology across 30 languages. The world's first astrology MCP server.