Problem
Today, neither single-tenant nor multi-tenant services can pass arbitrary MongoDB connection parameters (e.g., retryWrites=false) through lib-commons configuration.
Single-tenant (commons/mongo)
The Config struct only accepts URI, Database, MaxPoolSize, TLS, and Logger. There is no field for additional query parameters. Services like fetcher that use commons/mongo.NewClient directly have no way to inject parameters like retryWrites, directConnection, or tlsInsecure without hardcoding them in the URI string.
Current fetcher bootstrap (components/manager/internal/bootstrap/config.go):
func buildMongoSource(cfg *Config) string {
return buildCredentialURL(cfg.MongoURI, cfg.MongoDBUser, cfg.MongoDBPassword, cfg.MongoDBHost, cfg.MongoDBPort)
}
// buildCredentialURL builds: mongodb://user:pass@host:port
// No query parameters are supported.
func buildCredentialURL(scheme, user, password, host, port string) string {
targetURL := &url.URL{Scheme: scheme}
if user != "" || password != "" {
targetURL.User = url.UserPassword(user, password)
}
if port != "" {
targetURL.Host = net.JoinHostPort(host, port)
} else {
targetURL.Host = host
}
return targetURL.String()
}
Multi-tenant (commons/tenant-manager)
The core.MongoDBConfig struct has dedicated boolean fields for TLS, TLSSkipVerify, and DirectConnection, but there is no generic parameters field. The buildMongoQueryParams function in commons/tenant-manager/mongo/manager.go only translates these known fields:
// current: manager.go:1192-1238
func buildMongoQueryParams(cfg *core.MongoDBConfig) url.Values {
query := url.Values{}
// handles: authSource, directConnection, tls, tlsInsecure, tlsCAFile, tlsCertificateKeyFile
// does NOT handle: retryWrites, compressors, readPreference, w, journal, etc.
return query
}
Any new MongoDB driver parameter requires a code change in lib-commons — adding a field to MongoDBConfig, updating buildMongoQueryParams, releasing a new version, and updating all consumers.
midaz reference — single-tenant vs multi-tenant gap
Midaz single-tenant supports parameters via MONGO_*_PARAMETERS env vars and commons/mongo.BuildURI with URIConfig.Query:
// midaz config.mongo.onboarding.go:75-90 (single-tenant)
mongoPort, mongoParameters := pkgMongo.ExtractMongoPortAndParameters(cfg.OnbPrefixedMongoDBPort, cfg.OnbPrefixedMongoDBParameters, logger)
mongoQuery, _ := url.ParseQuery(mongoParameters)
mongoSource, _ := libMongo.BuildURI(libMongo.URIConfig{
// ...
Query: mongoQuery, // ← parameters go here
})
But in multi-tenant mode, midaz delegates entirely to tmmongo.Manager which reads config from the tenant-manager API. No parameters are passed from midaz — the MongoDBConfig struct returned by the tenant-manager controls everything:
// midaz config.mongo.onboarding.go:43-71 (multi-tenant)
func initOnboardingMultiTenantMongo(opts *Options, cfg *Config, logger libLog.Logger) (*onboardingMongoComponents, error) {
mongoMgr := tmmongo.NewManager(
opts.TenantClient,
opts.TenantServiceName,
mongoOpts...,
)
// No URI, no parameters — everything comes from tenant-manager API
// which is limited to MongoDBConfig struct fields
}
Proposed Solution
Add a generic Parameters map[string]string field to MongoDBConfig and merge it into buildMongoQueryParams:
1. commons/tenant-manager/core/types.go
type MongoDBConfig struct {
// ... existing fields ...
TLSSkipVerify bool `json:"tlsSkipVerify,omitempty"`
Parameters map[string]string `json:"parameters,omitempty"` // generic driver query params
}
2. commons/tenant-manager/mongo/manager.go
func buildMongoQueryParams(cfg *core.MongoDBConfig) url.Values {
query := url.Values{}
// ... existing logic for authSource, directConnection, tls ...
// Generic parameters — applied last so they can override defaults if needed
for k, v := range cfg.Parameters {
query.Set(k, v)
}
return query
}
Benefits
- Zero lib-commons changes for future MongoDB parameters (
compressors, readPreference, w, journal, etc.)
- Backward compatible — if
parameters is not present in JSON, map[string]string unmarshals to nil
- Products (midaz, fetcher, reporter) get automatic support without code changes
- Tenant-manager can expose a
parameters field per tenant for fine-grained control
Affected Code
| File |
Change |
commons/tenant-manager/core/types.go |
Add Parameters field to MongoDBConfig |
commons/tenant-manager/mongo/manager.go |
Merge cfg.Parameters in buildMongoQueryParams |
commons/tenant-manager/core/types_test.go |
Test cases for new field |
commons/tenant-manager/mongo/manager_test.go |
Test buildMongoQueryParams with parameters |
Context
Investigation triggered by fetcher needing tls=true&tlsInsecure=true&directConnection=true&retryWrites=false for MongoDB connections, which is not possible today in either single-tenant or multi-tenant mode without hardcoding in the URI.
/cc @brunobls
Problem
Today, neither single-tenant nor multi-tenant services can pass arbitrary MongoDB connection parameters (e.g.,
retryWrites=false) through lib-commons configuration.Single-tenant (
commons/mongo)The
Configstruct only acceptsURI,Database,MaxPoolSize,TLS, andLogger. There is no field for additional query parameters. Services like fetcher that usecommons/mongo.NewClientdirectly have no way to inject parameters likeretryWrites,directConnection, ortlsInsecurewithout hardcoding them in the URI string.Current fetcher bootstrap (
components/manager/internal/bootstrap/config.go):Multi-tenant (
commons/tenant-manager)The
core.MongoDBConfigstruct has dedicated boolean fields forTLS,TLSSkipVerify, andDirectConnection, but there is no generic parameters field. ThebuildMongoQueryParamsfunction incommons/tenant-manager/mongo/manager.goonly translates these known fields:Any new MongoDB driver parameter requires a code change in lib-commons — adding a field to
MongoDBConfig, updatingbuildMongoQueryParams, releasing a new version, and updating all consumers.midaz reference — single-tenant vs multi-tenant gap
Midaz single-tenant supports parameters via
MONGO_*_PARAMETERSenv vars andcommons/mongo.BuildURIwithURIConfig.Query:But in multi-tenant mode, midaz delegates entirely to
tmmongo.Managerwhich reads config from the tenant-manager API. No parameters are passed from midaz — theMongoDBConfigstruct returned by the tenant-manager controls everything:Proposed Solution
Add a generic
Parameters map[string]stringfield toMongoDBConfigand merge it intobuildMongoQueryParams:1.
commons/tenant-manager/core/types.go2.
commons/tenant-manager/mongo/manager.goBenefits
compressors,readPreference,w,journal, etc.)parametersis not present in JSON,map[string]stringunmarshals tonilparametersfield per tenant for fine-grained controlAffected Code
commons/tenant-manager/core/types.goParametersfield toMongoDBConfigcommons/tenant-manager/mongo/manager.gocfg.ParametersinbuildMongoQueryParamscommons/tenant-manager/core/types_test.gocommons/tenant-manager/mongo/manager_test.gobuildMongoQueryParamswith parametersContext
Investigation triggered by fetcher needing
tls=true&tlsInsecure=true&directConnection=true&retryWrites=falsefor MongoDB connections, which is not possible today in either single-tenant or multi-tenant mode without hardcoding in the URI./cc @brunobls