Problem
When a Python application needs to serve multiple Cloudinary accounts — for example a SaaS platform where each customer has their own Cloudinary credentials — the recommended approach is to call cloudinary.config() before each API call to switch accounts:
# Handler for User A's request
cloudinary.config(cloud_name="user_a_cloud", api_key="key_a", api_secret="secret_a")
result = cloudinary.uploader.upload(file)
This is unsafe on any shared server (threads, async frameworks, Django, Flask, etc.).
cloudinary.config() mutates a single module-level singleton (_config). If two requests arrive concurrently:
- Request A calls
cloudinary.config(cloud_name="cloud_a", api_key="key_a", ...)
- Request B calls
cloudinary.config(cloud_name="cloud_b", api_key="key_b", ...)
- Request A's upload now executes against cloud_b's credentials
This silently uploads assets to the wrong account, leaks data between tenants, or raises authentication errors that are hard to reproduce and diagnose.
Root cause
All SDK API functions (cloudinary.uploader.upload, cloudinary.api.*, cloudinary.provisioning.*) resolve credentials and routing by reading from the global cloudinary._config object at call time. There is no way to override this for a single call without temporarily mutating global state.
Expected behaviour
It should be possible to pass account configuration directly to any API call so that it applies only to that call, with no effect on the global config and no risk of cross-request contamination:
result = cloudinary.uploader.upload(
file,
cloudinary_config={
"cloud_name": "tenant_cloud",
"api_key": "tenant_key",
"api_secret": "tenant_secret",
},
)
Who is affected
Any application that:
- Manages multiple Cloudinary accounts from a single Python process
- Uses a multi-threaded or async web framework (Django, Flask, FastAPI, Gunicorn workers, Celery, etc.)
- Is building a multi-tenant SaaS product on top of Cloudinary
Problem
When a Python application needs to serve multiple Cloudinary accounts — for example a SaaS platform where each customer has their own Cloudinary credentials — the recommended approach is to call
cloudinary.config()before each API call to switch accounts:This is unsafe on any shared server (threads, async frameworks, Django, Flask, etc.).
cloudinary.config()mutates a single module-level singleton (_config). If two requests arrive concurrently:cloudinary.config(cloud_name="cloud_a", api_key="key_a", ...)cloudinary.config(cloud_name="cloud_b", api_key="key_b", ...)This silently uploads assets to the wrong account, leaks data between tenants, or raises authentication errors that are hard to reproduce and diagnose.
Root cause
All SDK API functions (
cloudinary.uploader.upload,cloudinary.api.*,cloudinary.provisioning.*) resolve credentials and routing by reading from the globalcloudinary._configobject at call time. There is no way to override this for a single call without temporarily mutating global state.Expected behaviour
It should be possible to pass account configuration directly to any API call so that it applies only to that call, with no effect on the global config and no risk of cross-request contamination:
Who is affected
Any application that: