What you actually operate when you host Evolution API
According to the official README, running Evolution API in production requires Node.js 20 or later, PostgreSQL or MySQL and, as a recommendation, Redis. There is also a ready-made Docker image. Installing is fast. The cost shows up day to day:
- A server sized for the number of connections, with room to grow.
- A database with backups, schema migrations on every release and monitoring.
- Updating the project when WhatsApp changes something in the WhatsApp Web protocol.
- Someone on call to find out why a server's connections dropped at two in the morning.
- Networking: every connection on a server goes out through the same IP unless you configure proxies.
For a small team, that competes directly with the product roadmap. That's what usually drives the search for an alternative: not a flaw in the project, but the time it takes. The broader comparison between the two models is in self-hosted vs managed.
Common reasons to look for an alternative
- Scaling without becoming an infrastructure team. Going from ten to three hundred connections takes more servers, load balancing and observability.
- Isolation between customers. In a SaaS product, one customer with risky sending behavior shouldn't affect the others on the same server.
- Predictable cost. Servers and engineering hours vary month to month; a price per connection goes straight into your margin spreadsheet.
- Support with response times. A community helps a lot, but it doesn't answer an incident on a schedule.
Evolution API and D-API compared
| Criteria | Evolution API | D-API |
|---|---|---|
| Model | Open source, you host it | Managed service |
| License and cost | Apache 2.0 with branding conditions; the cost is your infrastructure | Billed per connection, not per message |
| Connection types | WhatsApp Web (Baileys) and the official Cloud API | Unofficial (QR code) and the official Cloud API |
| Authentication | apikey header, with per-instance tokens | API key in the Authorization header |
| IP per connection | Depends on how you configure networking and proxies | Dedicated proxy with its own IP for each connection, included |
| Built-in integrations | Typebot, Chatwoot, RabbitMQ, Kafka, SQS, S3/MinIO and others | n8n, RabbitMQ and S3/MinIO; others through webhooks and HTTP |
| Who keeps it running | Your team | D-API, with self-healing and per-instance isolation |
Evolution has more native integrations with customer service tools. If your flow depends on several of them, weigh that. If what matters is operating time and isolation, the scale tips toward managed.
What changes when you migrate to D-API
You still have a REST WhatsApp API, with webhooks and both connection types. What comes off your list is the server. Each instance runs in its own environment, with its own credentials and webhook, and goes out through an IP that isn't shared with other numbers. If a connection drops, the platform tries to recover it on its own, and you receive the connection.status event to notify the customer.
Webhooks change hands too: if your endpoint fails, D-API makes up to 7 attempts with exponential backoff, with a 30-second timeout per attempt. If you already used a queue, you can also receive events through RabbitMQ, configured per session.
Migration guide from Evolution API
1. Translate the concepts
| On Evolution API | On D-API |
|---|---|
| Instance | Session, with a sessionId you define |
Global apikey header | Authorization header with the account API key, without Bearer |
| Instance-specific token | None: the account API key works for every session, and the sessionId goes in the body |
| Webhook and events per instance | Webhook per session, with one URL for everything or one URL per event |
| Cloud API connection | Session with type: "cloud_api" |
2. Create the sessions and route the events
The example creates a customer's session and splits incoming messages and connection status into different URLs, which helps if you currently handle everything in one giant endpoint:
curl -X POST https://api.d-api.cloud/api/v1/sessions \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "sessionId": "downtown-store", "type": "unofficial", "connectionMode": "qr" }'
curl -X POST https://api.d-api.cloud/api/v1/sessions/downtown-store/webhook-config \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"enabled": true,
"type": "per_event",
"events": {
"messages.received": { "enabled": true, "webhookUrl": "https://your-app.com/wa/messages" },
"connection.status": { "enabled": true, "webhookUrl": "https://your-app.com/wa/connection" }
}
}'
curl "https://api.d-api.cloud/api/v1/sessions/downtown-store/qr?image=1" \
-H "Authorization: YOUR_API_KEY" -o qr.png3. Swap the send calls
Sending text becomes POST /api/v1/messages/send/text with sessionId, to and text. Media, lists and groups follow the same pattern, with their own routes. In Node.js, the d-api-sdk package wraps these calls; see the Node.js SDK.
4. Reconnect the numbers and shut down the servers
Each number needs to scan a new QR code, or use the pairing code. Migrate in batches, confirm the status arrived as connected and that the message webhook is receiving, and only then shut down the matching instance on your server. Once the last number is out, the server, database and Redis dedicated to Evolution can be decommissioned.
To compare with another self-hosted option, see the WAHA alternative. Plans are on the pricing page, and the 3-day free trial, no credit card, lets you validate the migration with one number before moving the rest.
