Skip to content

feat: support generic MongoDB connection parameters in tenant-manager and single-tenant configs #437

@brunobls

Description

@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 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    staleNo recent activity — will be closed if not updated

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions