Why I Stopped Using Cloudinary, SendGrid, and Auth0
There's a point where the convenience of managed services flips into a liability — when you're spending more time managing vendor dashboards than building features. For me, that point was eight projects across six vendors, and the math stopped making sense.
Every new client project used to start the same way: sign up for Auth0, grab a SendGrid API key, configure Cloudinary, set up a Stripe account, wire up a database provider. By the time I had a working login page, I'd burned half a day creating accounts and copying secrets into .env files.
Then multiply that by eight projects.
The Breaking Point
I was managing credentials across Auth0, Cloudinary, SendGrid, Firebase, PlanetScale, and Stripe — each with its own dashboard, billing, API versioning, and breaking changes. When Auth0 changed their pricing tier and SendGrid deprecated an endpoint in the same week, I realized I was spending more time managing vendor relationships than writing features.
The real cost wasn't the subscription fees. It was the cognitive overhead of context-switching between six different dashboards, each with their own mental model of how things should work.
What I Built Instead
I run all my client projects on a single VPS. Instead of outsourcing every capability to a different vendor, I built platform-level services that auto-provision per project:
Storage — MinIO (S3-compatible) running locally. Same API as AWS S3, zero egress fees, no Cloudinary transformations I never used. Each project gets its own bucket with credentials auto-injected.
Email — Postfix on the VPS with a simple wrapper package. createEmailClient() gives me send(to, subject, template, variables). No API keys, no rate limit tiers, no deliverability dashboard I check once a year.
Auth — A centralized OAuth proxy at auth.hostkit.dev that handles Google, Apple, magic links, email/password, and anonymous sessions. Individual apps never touch provider consoles. One auth service, five providers, zero per-app configuration.
Database — PostgreSQL with per-project isolated databases. DATABASE_URL is auto-set on provisioning. Connection pooling handled at the ORM layer with a singleton pattern.
The Numbers
Before: ~$180/month across vendors for eight projects, plus 2-3 hours/month managing credentials and responding to deprecation emails.
After: $45/month for the VPS, zero vendor management time, and full control over every service.
What I Learned
The SaaS ecosystem optimizes for getting started fast — and it works. Auth0's quickstart is genuinely good. But nobody optimizes for managing twelve projects across six vendors, because that's not the common case they're selling to.
If you're running one app, use the managed services. They're worth it. But if you're an agency or a platform builder running multiple projects, the math changes completely. At some point, the overhead of managing vendors exceeds the overhead of running the services yourself.
The key insight: I didn't need Cloudinary's image transformations, SendGrid's analytics dashboard, or Auth0's enterprise SSO. I needed file uploads, transactional email, and login. Those are solved problems. The vendor complexity was buying me features I never used.
The Tradeoff
I won't pretend this is free. I'm now responsible for uptime, backups, and security patches on services I used to outsource. But I was already responsible for debugging integration issues with those vendors — and at least now when something breaks, I can read the source code.
