Releases: gofr-dev/gofr
v1.42.0
v1.42.0
🚀 Features
1. CockroachDB Support
GoFr now supports CockroachDB, a distributed cloud-native SQL database.
Developers can now configure GoFr services to connect to CockroachDB using simple environment variables.
🔧 Configuration:
DB_DIALECT=cockroachdb
DB_HOST=localhost
DB_PORT=26257
DB_USER=root
DB_PASSWORD=your-password
DB_NAME=defaultdb
DB_SSL_MODE=require
For more details, refer to the SQL usage guide.
🛠️ Improvements
1. gRPC Reflection Toggle via Config
GoFr now supports enabling/disabling gRPC server reflection using a simple config flag:
GRPC_ENABLE_REFLECTION=true
🔍 When to enable:
-
Development & Debugging: Use with tools like grpcurl, Postman, or Evans.
-
Internal Networks: Safe in private, trusted environments.
-
CI/CD Pipelines: Ideal for service discovery in automated setups.
This allows dynamic inspection of gRPC services while maintaining control over exposure.
🛠️ Fixes
1. Supabase Healthcheck Issue Resolved
Resolved an issue where Supabase-backed services were not responding properly to health checks due to incorrect handling of internal pings.
2. Fixed Data Race in Metrics Gauges
Addressed a concurrency bug where the internal float64Gauge
map was accessed without synchronization. Proper locking is now in place around map access to avoid data races during concurrent SetGauge
and metric reads.
3. App Name & Version Initialization Bug
Fixed a configuration issue where AppName
and AppVersion
were incorrectly defaulting to gofr-app
and dev
, even when explicitly provided by the user. These values now correctly reflect user-specified configuration during startup.
v1.41.0
v1.41.0
🔧 Improvements
1. New HTTP Error Type: ErrorRecordNotFound
A new standardized error type http.ErrorRecordNotFound
has been introduced to gracefully handle scenarios where no records are found in the database.
Example:
return nil, http.ErrorRecordNotFound{
Message: "User not found with the given ID",
}
This improves semantic clarity and enables better client-side handling for empty-query results.
2. Improved Cron Job Observability
All cron jobs in GoFr now come with built-in logger and tracing support.
-
Logs from scheduled tasks are now clearly visible.
-
Each recurring job run is automatically tagged with a unique trace ID, making it easier to trace, debug, and monitor scheduled executions across your system.
This ensures better observability for background tasks without requiring additional instrumentation.
🐛 Fixes
1. Supabase Connection Issue Resolved
Previously, Supabase connections were not initializing correctly in GoFr due to a missing dialect registration. Supabase-backed services will now connect without issues—no manual fixes required.
v1.40.1
v1.40.1
🔧 Dependency Updates
Upgraded all externalized datasource dependencies to their latest stable versions for improved performance, security, and compatibility across supported services.
v1.40.0
v1.40.0
🚀 Features
Support for Supabase Database
Users can now connect their GoFr services to a Supabase database using environment variables. This feature supports both direct and pooled connections, enabling secure and scalable Postgres usage via Supabase.
🔧 Environment Variable Setup:
DB_DIALECT=supabase
DB_HOST=db.[PROJECT_REF].supabase.co # Optional, derived from PROJECT_REF
DB_USER=postgres # Or database user name
DB_PASSWORD=password
DB_NAME=postgres # Or your database name
DB_PORT=5432 # Optional, defaults based on connection type
DB_SSL_MODE=require # Optional, forced to "require" for Supabase
# Supabase-specific configs
SUPABASE_PROJECT_REF=your_project_ref
SUPABASE_CONNECTION_TYPE=direct # Options: direct, session, transaction
SUPABASE_REGION=us-east-1 # Required for pooled connections
# Alternatively, can provide full connection string
DATABASE_URL=postgresql://postgres:password@db.your_project_ref.supabase.co:5432/postgres
Inter-Service WebSocket Communication
GoFr now supports Inter-Service WebSocket Communication, enabling services to exchange real-time messages over WebSocket connections. Ideal for microservices needing live updates or event-driven communication.
🔑 Key Methods:
-
AddWSService
: Register a persistent WebSocket connection to another service with optional auto-reconnect. -
WriteMessageToService
: Send messages to any registered service.
✅ Example Usage:
func main(){
app := gofr.New()
err := app.AddWSService("notification-service", "ws://notifications.example.com/ws", nil, true, 5*time.Second)
if err != nil {
app.Logger.Errorf("Failed to add WebSocket service: %v", err)
return
}
app.POST("/send-notification", func(ctx *gofr.Context) (any, error) {
message := map[string]string{
"title": "New Message",
"content": "You have a new notification!",
}
err := ctx.WriteMessageToService("notification-service", message)
if err != nil {
return nil, err
}
return "Notification sent successfully!", nil
})
app.Run()
}
This enables resilient, real-time service communication with minimal configuration.
🔧 Improvements
1. New HTTP Error Type: ServiceUnavailable
A new standardized error type ErrorServiceUnavailable
has been introduced for representing service unavailability due to dependency issues like database failures or third-party service outages.
⚙️ Use Case Example:
err := http.ErrorServiceUnavailable{
Dependency: "PostgreSQL",
ErrorMessage: "Connection timeout",
}
This improvement enhances observability and clarity when dealing with critical external failures.
v1.39.1
v1.39.1
🛠 Improvements
-
Disable Logs for Health & Alive Probes
Logging for health check routes (
/.well-known/health
and/.well-known/alive
) can now be disabled to reduce log clutter in environments with frequent probe calls (e.g., Kubernetes).Set the following environment variable:
LOG_DISABLE_PROBES=true
-
TraceID Now Included in Context-Based Logging
Logs emitted using
ctx.Logger()
now automatically include the requesttraceID
. This enhances traceability across services and allows easier debugging in distributed systems.Example log before:
{"message": "User created", "level": "INFO"}
After:
{"message": "User created", "trace_id": "3ac9f5e7c12e...", "level": "INFO"}
No additional configuration needed—this is now built-in.
-
Enhanced ArangoDB Query Options Support
You can now pass advanced query and subquery options when executing AQL queries via GoFr’s ArangoDB client.
options := map[string]any{ "count": true, "batchSize": 100, "options": map[string]any{ "fullCount": true, "profile": 2, }, }
Supported keys include (but are not limited to):
-
QueryOptions:
count
,batchSize
,ttl
,cache
,memoryLimit
-
QuerySubOptions (under
options
key):fullCount
,allowRetry
,stream
,optimizer
,profile
,maxRuntime
,skipInaccessibleCollections
, and more
Example usage:
err := ctx.ArangoDB.Query(ctx, "myDatabase", query, bindVars, &results, options)
This update gives you full control over AQL query execution for performance tuning, streaming, profiling, and more.
-
v1.39.0
v1.39.0
🚀 Features
gRPC Streaming Support
GoFr now supports all gRPC streaming types, unlocking full duplex communication capabilities:
- Server-side streaming
- Client-side streaming c
- Bidirectional streaming
Auto-generated handlers for streaming methods with built-in metrics and tracing support for all streaming calls
Note: Requires
gofr-cli v0.7.0
or higher.
Refer to the examples to explore usage patterns.
Redirect Support in HTTP Handlers
Handlers can now trigger client redirects by returning a response.Redirect
object:
import (
"gofr.dev/pkg/gofr"
"gofr.dev/pkg/gofr/http/response"
)
func main() {
app := gofr.New()
app.GET("/old-page", func(ctx *gofr.Context) (any, error) {
return response.Redirect{URL: "https://example.com/new-page"}, nil
})
app.Run()
}
Use this for SEO-friendly permanent or temporary redirects from legacy URLs.
🛠 Improvements
1. TLS Support for Redis
Redis connections in GoFr can now be secured using TLS. This enhancement enables secure communication in production and enterprise deployments. Configuration is done via environment variables:
Environment Variable | Description |
---|---|
REDIS_TLS_ENABLED |
Set to "true" to enable TLS support |
REDIS_TLS_CA_CERT_PATH |
File path to the CA certificate to verify Redis server identity |
REDIS_TLS_CERT_PATH |
File path to the client certificate (for mTLS connections) |
REDIS_TLS_KEY_PATH |
File path to the client private key (for mTLS connections) |
v1.38.0
Release - v1.38.0
🚀 Features
Elasticsearch Integration Support
-
GoFr now supports Elasticsearch as a pluggable data source with a standard interface for document indexing, searching, and cluster management.
-
Developers can inject any compatible Elasticsearch client that implements the following interface:
type Elasticsearch interface { Connect() CreateIndex(ctx context.Context, index string, settings map[string]any) error DeleteIndex(ctx context.Context, index string) error IndexDocument(ctx context.Context, index, id string, document any) error GetDocument(ctx context.Context, index, id string) (map[string]any, error) UpdateDocument(ctx context.Context, index, id string, update map[string]any) error DeleteDocument(ctx context.Context, index, id string) error Search(ctx context.Context, indices []string, query map[string]any) (map[string]any, error) Bulk(ctx context.Context, operations []map[string]any) (map[string]any, error) HealthChecker }
-
Official GoFr-compatible driver is available via:
go get gofr.dev/pkg/gofr/datasource/elasticsearch@latest
-
Example usage in your
main.go
:func main (){ app := gofr.New() es := elasticsearch.New(elasticsearch.Config{ Addresses: []string{"http://localhost:9200"}, Username: "elastic", Password: "changeme", }) app.AddElasticsearch(es) app.Run () }
-
Checkout our official documentation for more details.
v1.37.1
Release - v1.37.1
🚀 Improvements
Extended Error Responses (RFC 9457-style)
-
GoFr now supports extended error responses following the RFC 9457 specification.
-
Developers can implement the new
ResponseMarshaler
interface to enrich error responses with custom fields beyond the standard error message and status code.type ResponseMarshaler interface { Response() map[string]any }
-
Example:
type ValidationError struct { Field string Message string Code int } func (e ValidationError) Error() string { return e.Message } func (e ValidationError) StatusCode() int { return e.Code } func (e ValidationError) Response() map[string]any { return map[string]any{ "field": e.Field, "type": "validation_error", "details": "Invalid input format", } }
⚠️ Note: Themessage
field is automatically populated from theError()
method. Custom fields with the name "message" in theResponse()
map should not be used as they will be ignored in favor of theError()
value.This feature allows more descriptive and structured error responses, ideal for client-side validation, API debugging, and frontend integration.
🛠 Fixes
1. WebSocket: Fixed Concurrent Write Panic
- WebSocket writes are now thread-safe. Previously, concurrent calls to
WriteMessageToSocket()
caused race conditions and panics. Writes are now internally synchronized.
2. NATS: Synchronous Connection Setup
- NATS connections are now established synchronously to prevent
errJetStreamNotConfigured
errors when callingjetStream()
immediately afterConnect()
.
v1.37.0
🚀 Features
1. Dgraph Migration Support
- Added native migration capabilities for Dgraph through new methods, enabling precise schema evolution:
// Apply or update the complete Dgraph schema ApplySchema(ctx context.Context, schema string) error // Atomically create or update a field definition AddOrUpdateField(ctx context.Context, fieldName, fieldType, directives string) error // Permanently remove a field/predicate and its associated data DropField(ctx context.Context, fieldName string) error
- Refer to the official documentation for full usage details.
🛠 Improvements
1. gRPC Server Configuration via AddGRPCServerOptions
-
GoFr now allows configuring advanced gRPC
ServerOptions
. -
Example: Enabling TLS and setting a connection timeout
creds, _ := credentials.NewServerTLSFromFile("server-cert.pem", "server-key.pem") app.AddGRPCServerOptions( grpc.Creds(creds), grpc.ConnectionTimeout(10*time.Second), )
-
Refer to the official documentation to know more.
2. Add Custom Unary Interceptors
app.AddGRPCUnaryInterceptors(authInterceptor)
-
GoFr already logs, traces and sends default metrics for all gRPC calls. No external interceptor for such features is necessary. Custom server-side
UnaryServerInterceptors
can now be registered easily for use cases like:- Authentication
- Request validation
-
For guidance on how to define Server UnaryInterceptors that can be added in your GoFr's gRPC server, check out the official documentation.
3. Advanced gRPC Client DialOptions Support
-
Clients can now be customized extensively via
grpc.DialOptions
.
This allows to add gRPC services with :
- Secure TLS communication
- Load-balanced connections
- Retry logic
- Context-aware metadata injection (useful for tracing and auth)const serviceConfig = `{ "loadBalancingPolicy": "round_robin", "methodConfig": [{ "name": [{"service": "HelloService"}], "retryPolicy": { "maxAttempts": 4, "initialBackoff": "0.1s", "maxBackoff": "1s", "backoffMultiplier": 2.0, "retryableStatusCodes": ["UNAVAILABLE", "RESOURCE_EXHAUSTED"] } }] }` // Metadata interceptor to add client ID to each request func MetadataUnaryInterceptor(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption, ) error { md := metadata.Pairs("client-id", "f1b1a372-02f5-4065-9ccf-113d34a3d5ed") ctx = metadata.NewOutgoingContext(ctx, md) return invoker(ctx, method, req, reply, cc, opts...) } func main() { app := gofr.New() creds, err := credentials.NewClientTLSFromFile("cert.pem", "") if err != nil { app.Logger().Errorf("TLS error: %v", err) return } grpcClient, err := client.NewHelloServiceGoFrClient( app.Config.Get("GRPC_SERVER_HOST"), app.Metrics(), grpc.WithTransportCredentials(creds), grpc.WithDefaultServiceConfig(serviceConfig), grpc.WithChainUnaryInterceptor(MetadataUnaryInterceptor), ) if err != nil { app.Logger().Errorf("Failed to create client: %v", err) return } handler := NewGreetHandler(grpcClient) app.GET("/hello", handler.Hello) app.Run() }
- Refer to the official documentation to know more.
🛠 Fixes
1. SurrealDB Update
Method: Unexpected Behavior Fixed
- Regardless of the input, the
Update
method previously inserted an unexpected hardcoded key-value pair. The method now correctly updates only the intended fields as passed by the caller.
v1.36.0
Release - v1.36.0
🚀 Features
1. SurrealDB Migration Support
- Added support for database migration operations in SurrealDB.
- Supported methods include:
// Creates a new namespace in SurrealDB. CreateNamespace(ctx context.Context, namespace string) error // Creates a new database in SurrealDB. CreateDatabase(ctx context.Context, database string) error // Deletes a namespace from SurrealDB. DropNamespace(ctx context.Context, namespace string) error // Deletes a database from SurrealDB. DropDatabase(ctx context.Context, database string) error
- Refer to our official documentation to know more.
🛠 Improvements
1. Default Metrics for SurrealDB Data Source
- Introduced default metric collection for SurrealDB at the specified
METRICS_PORT
, enabling better observability and performance monitoring.
2. JWT Claim Validations
EnableOAuth
now takes an additional JWT validation options asjwt.ParserOption
, allowing fine-grained control over claim validation.- Example :
app.EnableOAuth( "http://jwks-endpoint", 20, jwt.WithExpirationRequired(), // to enforce presence of exp claim in every token jwt.WithAudience("https://api.example.com"), jwt.WithIssuer("https://auth.example.com") )
- To know more about the different claim validation options, check out our official documentation.
🛠 Fixes
1. pprof
Profiling Enhancements
- Previously, the
pprof
endpoint was restricted to being enabled only when theAPP_ENV=DEBUG
environment variable was set, and it ran on the specifiedHTTP_PORT
. This prevented users from loading their different environments, for e.g. stage or production configurations if we setAPP_ENV
asDEBUG
for profiling. - GoFr now automatically enables
pprof
profiling onMETRICS_PORT
(default:2121
). - Profiling endpoints include :
/debug/pprof/cmdline
/debug/pprof/profile
/debug/pprof/symbol
/debug/pprof/trace
/debug/pprof/
(index)
For more information on setting up and using profiling in your application, refer to our official documentation.