Self-Hosting a CRM: Why We Moved Away from SaaS
The SaaS CRM market is not short of options. Salesforce, HubSpot, Pipedrive, Zoho — each with its own pricing tier, feature matrix, and account manager ready to explain why the next tier up is exactly what your business needs. We used several of these tools over the years and found that, beyond a certain point, the value proposition inverts.
The costs are the most visible symptom. Pipedrive starts reasonably, then scales per seat. HubSpot’s free tier is functional until the moment it is not, at which point the jump to a paid plan is substantial. Salesforce operates in a different category entirely: it is enterprise software priced accordingly, requiring dedicated administrators to configure and maintain it. For a consulting firm managing a few hundred contacts and a handful of active deals, none of these pricing structures are particularly efficient.
But the cost calculation is not purely about subscription fees. There is also the question of what you are actually buying.
The Lock-in Problem
SaaS CRM vendors sell convenience. In exchange, they retain custody of your data, control over the interface, and the ability to change pricing at their discretion. This is not a controversial observation — it is the model. Salesforce has raised prices multiple times. HubSpot has restructured feature gating across its tiers. Pipedrive has introduced seat minimums on plans that previously had none. Each of these moves is entirely within the vendor’s rights, and each creates friction for customers who built workflows around the previous terms.
The data portability question is more salient than most discussions acknowledge. Every major CRM offers export functionality, typically to CSV. But a CSV export of your contact data is not the same as your CRM data. Relationships between contacts and companies, activity history, deal timelines, custom fields — these rarely survive an export cleanly. In practice, migrating away from a SaaS CRM means rebuilding significant portions of your operational history from scratch. The data is technically yours, but recovering it in a useful form requires substantial effort.
Twenty CRM and the Self-Hosting Option
Twenty (twenty.com) is an open-source CRM that has emerged as a serious alternative to commercial offerings. The codebase is actively developed, the data model is well-structured, and the interface is genuinely usable. It runs on PostgreSQL, which means standard database tooling applies directly. The project is not a hobby repository — it has a funded team behind it and a clear roadmap.
We deployed it on our existing Hetzner infrastructure, the same CX53 instance that runs our website and other services behind Traefik. The Docker Compose configuration Twenty provides is straightforward. The core services are the API server, the frontend, the PostgreSQL database, and Redis for caching and queue management. Total resource overhead for a small team is modest: the stack consumes under 2 GB of RAM at idle.
The setup process took roughly two hours, including DNS configuration and SSL termination through our existing Traefik reverse proxy. The Twenty documentation covers the Docker deployment path clearly. Environment variables are well-documented, health checks work as expected, and the initial data migration runs automatically on first startup. There were no meaningful obstacles.
What the Cost Analysis Actually Shows
Running Twenty self-hosted on infrastructure we already operate costs effectively nothing in incremental terms. On dedicated infrastructure, the cost is the monthly server bill. Our Hetzner CX53 runs at approximately €30 per month and hosts multiple services — the CRM is one tenant in a shared environment, not the reason the server exists.
Compare that to common SaaS alternatives. Pipedrive runs $24–67 per seat per month depending on tier. For a three-person team, that is $72–201 per month, or $864–2,412 per year. HubSpot’s Professional tier, which unlocks automation and custom reporting, runs $800 per month for five seats. Salesforce Essentials — the entry point — starts at $25 per seat per month, but the features most sales teams actually require sit at the Professional tier at $75 per seat.
None of these figures are unreasonable for large sales organizations where CRM adoption directly drives measurable pipeline value. But for a technical consulting firm where the CRM is primarily a contact database and engagement history, the calculus is different. The operational overhead of a self-hosted deployment is measured in hours per year, not per week. The breakeven is reached quickly.
Data Ownership in Practice
When your CRM data lives in a PostgreSQL database you control, the operational implications are concrete. Backups are standard database dumps — we run daily pg_dump exports to Hetzner Object Storage, retained for 30 days with monthly snapshots held for a year. Queries are unrestricted. You can join CRM tables against your own data, build custom reports against the raw schema, or feed contact data into other internal systems without export rate limits or API call quotas.
This matters more than it initially appears. SaaS CRMs impose API rate limits that become architectural constraints at scale. HubSpot’s free tier limits requests to 500 per day. Pipedrive’s limits vary by plan. When you need to synchronize CRM data with external systems — billing tools, project management, custom dashboards — these limits shape what integrations are architecturally feasible. With a self-hosted PostgreSQL database, the only constraint is the server’s capacity.
There is also the question of what happens to your data if the vendor is acquired, changes its terms, or ceases operations. These are low-probability events for the major vendors, but they are not zero-probability events. Owning your data means owning the risk model, not delegating it.
Customization Without a Development Partner
Twenty is built on a GraphQL API with a metadata-driven data model. Adding custom fields to any entity takes seconds in the interface — you define the field type, it appears immediately in the UI and in the API schema. No configuration exports, no sandbox deployments, no support tickets, no tier upgrade required.
This is qualitatively different from what SaaS CRMs offer. Salesforce allows extensive customization, but the customization model is complex enough to sustain an entire professional services industry around it. Pipedrive allows custom fields on most objects, but interface customization is limited. HubSpot’s customization capabilities depend heavily on which plan you are paying for.
The Twenty approach — open schema, local control — means that when an engagement requires tracking information the default data model does not cover, you extend it directly. For a consulting firm that sometimes needs to track unusual deal structures or client-specific metadata, this flexibility has proven genuinely useful.
Backup Strategy
Our backup configuration is intentionally simple. A daily automated pg_dump of the Twenty PostgreSQL database, compressed and uploaded to Hetzner Object Storage. Application data — profile images, attachments — lives in a Docker volume backed up via restic on the same schedule. Retention is 30 days for daily snapshots, 12 months for monthly snapshots.
Recovery testing runs quarterly: restore the backup to a staging database, verify row counts, spot-check data integrity. A full restore from backup to an operational Twenty instance takes approximately 15 minutes — acceptable for a tool that is not on the critical path for real-time operations. Hetzner Object Storage costs €6 per month for 1 TB; our CRM backups consume a small fraction of that allocation.
The operational discipline required here is modest. Backup jobs run as cron tasks on the host, log their results to a monitoring system, and alert on failure. This is standard infrastructure practice that any team running server workloads should already have in place.
When Self-Hosting Makes Sense
The case for self-hosting a CRM is strongest when several conditions align. Your team has genuine operational capacity to run Docker containers and manage a PostgreSQL database — this is a real prerequisite, not a technicality. You already operate server infrastructure with available capacity. Your CRM use case is relatively stable, meaning you are not dependent on the vendor’s roadmap for features you will need within the next quarter.
The cost and data ownership arguments are real, but they are secondary to the operational capacity question. Self-hosting trades money for time and expertise. If your team’s operational time is more expensive than a SaaS subscription, the economics may not favor the switch. The breakeven is not purely financial — it is also a function of where your team’s skills and bandwidth actually are.
When It Does Not
If your organization needs deep enterprise integrations — a CRM connected to a marketing automation platform, a CDP, and a data warehouse, all maintained by a dedicated RevOps function — self-hosting is the wrong direction. The integration ecosystem around commercial CRMs is deep because the vendors have invested years in building it. A self-hosted Twenty instance connects through its GraphQL API or direct database access. It does not have a library of 500 pre-built connectors.
Similarly, if no one on your team can diagnose a failing Docker container, read PostgreSQL logs, or restore from a database backup, the operational burden will exceed the cost savings quickly. The self-hosting path requires a baseline of infrastructure competence that not every team has — and acquiring that competence carries a cost of its own.
Compliance requirements can also shift the equation. If your business operates under regulations that require certified data handling from technology vendors — SOC 2 attestations, ISO 27001 audits — a self-hosted deployment means those certifications must apply to your own infrastructure. Whether that is an advantage or a burden depends on your existing compliance posture.
What We Actually Run
Our production Twenty deployment has been running for several months without a meaningful incident. Contact management, company records, deal tracking, and activity logging all function as expected. The interface is clean enough that onboarding required no formal training. The GraphQL API has proven useful for pulling CRM context into other internal tooling — specifically for client reporting and engagement tracking that we build ourselves rather than purchasing as a SaaS add-on.
Maintenance is lower than anticipated. Twenty releases updates at a steady cadence; deploying them is a matter of pulling the new Docker image and restarting the service, typically under five minutes. The PostgreSQL database has not required manual intervention beyond routine backup verification.
The decision was not ideological. We did not move away from SaaS CRM because SaaS is inherently wrong or because self-hosting is inherently virtuous. The decision was operational: for our specific use case, the self-hosted path is simpler, cheaper, and gives us better control over data that belongs to us. For an organization with different constraints — a larger sales team, deeper integration requirements, or limited infrastructure capacity — the conclusion might be different. The point is to make the calculation explicitly rather than defaulting to the subscription model because it is the path of least resistance.
Related Insights
- Traefik Reverse Proxy: The Complete Self-Hosting Guide for HTTPS and SSL Automation
- Self-Hosting n8n on Hetzner Cloud: Complete Docker Setup Tutorial
- How Complete Data Ownership Transforms Amazon Selling Operations
- Building a Multi-Tenant Development Stack with Docker: Complete Setup for Scalable Client Deployments