Building a Hosting Platform from Scratch: The Makdos Story
Between 2020 and 2023, I built and operated Makdos, a hosting platform that grew to serve 500 to 1,000 customers and generated roughly half a million dollars in annual revenue. This is the story of how it went from a blank repository to a production system handling real money, real customers, and real expectations.
The Genesis
The hosting market in Turkey has always been crowded with resellers repackaging the same cPanel-based solutions. Most offered identical features, identical interfaces, and identical limitations. I saw an opportunity to build something different: a modern hosting platform with a custom control panel, better developer experience, and infrastructure designed for reliability rather than cost-cutting.
I started building Makdos in early 2020, just as the world was entering lockdown. The timing was accidental but fortunate -- demand for online services was skyrocketing, and businesses were rushing to get their web presence established or upgraded.
The Technology Stack
Choosing the right stack was critical because I knew this would be a long-term project with complex requirements. Here is what I settled on and why.
The frontend was built with React and later migrated to Next.js for better SEO and server-side rendering of the marketing pages. The customer dashboard was a single-page React application with a custom component library that matched our brand. I used Tailwind CSS for styling, which kept the design consistent and made it easy to iterate quickly.
The backend was split between Node.js for the customer-facing API and Python with FastAPI for the infrastructure management layer. Node.js handled authentication, billing, support tickets, and the general CRUD operations that power any SaaS platform. Python and FastAPI handled the heavy lifting: provisioning servers, managing DNS records, configuring web servers, and interfacing with the underlying Linux systems.
Why two languages? Node.js is excellent for building web APIs quickly, but infrastructure automation is Python's domain. The ecosystem of libraries for system administration, server configuration, and cloud provider APIs is vastly richer in Python. FastAPI gave me the performance and type safety I needed, along with automatic API documentation via OpenAPI.
PostgreSQL was the primary database, chosen for its reliability, extensibility, and the excellent tooling ecosystem around it. I used Redis for caching, session storage, and as a message broker for background job processing.
Building the Control Panel
The control panel was the product's face. It needed to be intuitive enough for non-technical users (small business owners setting up their first website) while powerful enough for developers who wanted fine-grained control.
I designed the panel around the concept of "services" -- each customer could have multiple services (shared hosting, VPS, domain, SSL certificate), and each service had its own management interface. The React component architecture mapped naturally to this model. Each service type had its own set of components for configuration, monitoring, and management.
File management was one of the trickiest features. I built a web-based file manager that supported drag-and-drop uploads, in-browser code editing with syntax highlighting, and permission management. The file manager communicated with the backend via WebSocket for real-time progress updates during large uploads.
Database management was another significant feature. Customers could create, backup, and restore MySQL and PostgreSQL databases directly from the panel. The backup system supported both manual snapshots and automated daily backups with configurable retention policies.
The Provisioning Engine
The provisioning engine was the most complex piece of the entire system. When a customer ordered a new hosting plan, the system needed to automatically create a Linux user, configure disk quotas, set up a web server virtual host, create an FTP account, configure email routing, provision SSL certificates, and update DNS records. All of this had to happen reliably, idempotently, and within a few seconds.
I built the provisioning engine in Python using a task queue pattern with Celery and Redis. Each provisioning step was an individual Celery task, and the overall provisioning workflow was a Celery chain that executed steps in sequence. If any step failed, the system would retry it automatically and, after a configurable number of retries, roll back the entire chain.
Idempotency was a core design principle. Every provisioning task could be run multiple times without causing side effects. This was essential for reliability -- if a task timed out and was retried, it should not create duplicate resources or leave the system in an inconsistent state.
Billing and Subscription Management
A hosting platform is fundamentally a billing system with a technical layer on top. Getting billing right was critical for revenue and customer trust.
I implemented a subscription-based billing system with monthly and annual plans. Customers could upgrade, downgrade, or cancel their plans at any time, with prorated credits applied automatically. The billing engine calculated invoices, processed payments through local Turkish payment processors, and handled failed payment retries with configurable grace periods.
Invoice generation was more complex than I initially expected. Turkish tax regulations require specific invoice formats, and the rules changed during the three years I operated the platform. I abstracted the invoice generation logic behind an interface so that regulatory changes only required updating a single module.
Monitoring and Operations
Running a hosting platform means being responsible for other people's websites and applications. If our infrastructure goes down, our customers' businesses go down. The monitoring stack I built reflected this responsibility.
I used Prometheus and Grafana for infrastructure monitoring, with custom exporters for application-specific metrics like provisioning success rates, billing transaction volumes, and customer support response times. Alerting was configured through Alertmanager with escalation policies -- a warning to Slack, a critical alert to my phone.
Customer-facing monitoring was also important. Each hosting account had a status page showing resource usage (CPU, memory, disk, bandwidth), recent access logs, and error logs. This reduced support tickets significantly because customers could diagnose common issues themselves.
Scaling the Business
Growing from 0 to 500+ customers required constant iteration on both the product and the infrastructure. I learned to prioritize features based on support ticket patterns -- if multiple customers were asking for the same thing, it went to the top of the backlog.
Customer support was handled through an integrated ticket system that I built into the control panel. Support agents could see the customer's services, resource usage, and recent activity alongside the ticket, which dramatically reduced resolution times.
Infrastructure scaling followed a predictable pattern. As customer counts grew, I added more shared hosting nodes, each configured identically using Ansible playbooks. This Infrastructure-as-Code approach meant that spinning up a new node took minutes rather than hours.
The Revenue Journey
Reaching approximately 500,000 dollars in annual revenue was not a straight line. The first year was slow -- building the product, acquiring early customers, and iterating based on feedback. The second year saw significant growth as word-of-mouth and SEO started driving consistent traffic. By the third year, the platform was generating stable recurring revenue with healthy margins.
Pricing strategy evolved over time. I started with aggressive pricing to attract early adopters, then gradually increased prices as the feature set matured. Annual plans with a discount were the most popular option and provided predictable cash flow.
What I Would Do Differently
If I were starting Makdos today, I would invest in automated testing earlier. The provisioning engine, in particular, needed comprehensive integration tests that I only added after experiencing several production incidents.
I would also build a more robust API from the start. As the platform grew, we needed to support third-party integrations, and retrofitting a clean, versioned API onto an existing system was painful.
Finally, I would separate the infrastructure management layer into a truly independent service earlier. The coupling between the web application and the provisioning engine created deployment challenges that a cleaner architecture would have avoided.
The Bigger Picture
Building Makdos taught me that a successful platform is not just code -- it is operations, support, billing, and trust. The technical challenges were real and substantial, but the operational challenges were equally demanding. Managing a hosting platform gave me a perspective on full-stack engineering that goes well beyond writing application code.