Developer Guide: Node.js Express WhatsApp Integration Using MessageBird
Integrate WhatsApp messaging into your Node.js applications using MessageBird's powerful Conversations API. This guide provides a complete walkthrough for building a production-ready Express application capable of sending and receiving WhatsApp messages, handling errors, ensuring security, and deploying reliably.
We'll build a simple ""echo bot"" 🤖 – an application that receives WhatsApp messages via a MessageBird webhook and replies with the same message content. This serves as a foundational example demonstrating the core integration mechanics.
Project Overview and Goals
What We're Building:
A Node.js application using the Express framework that:
- Sends outbound WhatsApp messages via the MessageBird API.
- Receives inbound WhatsApp messages via a MessageBird Webhook.
- Replies to incoming messages (simple echo functionality).
- Includes robust error handling, security considerations, and deployment guidance.
Problem Solved:
This guide enables developers to programmatically interact with users on WhatsApp, facilitating customer support, notifications, alerts, or chatbot functionality directly within their Node.js applications, leveraging MessageBird's reliable infrastructure.
Technologies Used:
- Node.js: Asynchronous JavaScript runtime environment.
- Express: Minimalist and flexible Node.js web application framework.
- MessageBird Conversations API: The third-party service used to send and receive WhatsApp messages.
axios
: Promise-based HTTP client for making API requests to MessageBird.dotenv
: Module to load environment variables from a.env
file.crypto
: Node.js module for cryptographic functions (used for webhook signature verification).
Why These Technologies?
- Node.js/Express: A popular, efficient, and scalable choice for building web servers and APIs in JavaScript.
- MessageBird: Provides a unified API (Conversations API) to manage multiple messaging channels, including WhatsApp, simplifying integration compared to managing the WhatsApp Business API directly. Handles infrastructure, scaling, and compliance aspects.
axios
: A standard and easy-to-use library for making HTTP requests.dotenv
: Best practice for managing configuration and secrets during development.
System Architecture:
+-----------------+ +---------------------+ +---------------------+ +-----------------+
| User (WhatsApp) | <--> | WhatsApp Platform | <--> | MessageBird Service | <--> | Node.js/Express |
| | | (Meta Infrastructure)| | (Conversations API) | | Application |
+-----------------+ +---------------------+ +---------------------+ +-----------------+
^ | | ^ (API Calls)
| | (Messages) | | (Webhook Post)
v | v |
+---------------------------------------------------------------------------------+
| 1. User sends message to App's WhatsApp number. |
| 2. WhatsApp platform routes message to MessageBird. |
| 3. MessageBird POSTs message data to App's configured Webhook URL. |
| 4. App verifies webhook signature, processes message. |
| 5. App makes API call to MessageBird (Conversations API) to send reply. |
| 6. MessageBird sends reply via WhatsApp Platform to the User. |
+---------------------------------------------------------------------------------+
Prerequisites:
- Node.js and npm (or yarn): Installed on your development machine. Download Node.js
- MessageBird Account: A registered account with MessageBird. Sign up for MessageBird
- Approved WhatsApp Business Channel: You must have gone through MessageBird's WhatsApp onboarding process and have an active, approved WhatsApp channel connected to your account. Note the
Channel ID
. - MessageBird API Key: An API Access Key (Live key required for actual sending/receiving).
- MessageBird Webhook Signing Key: Used to verify incoming webhooks.
- Publicly Accessible URL: For MessageBird to send webhooks to during development (we'll use
ngrok
for this, but production requires a stable, deployed URL - see Deployment section).
1. Setting Up the Project
Let's initialize our Node.js project and install the necessary dependencies.
-
Create Project Directory: Open your terminal and create a new directory for your project, then navigate into it.
mkdir node-messagebird-whatsapp cd node-messagebird-whatsapp
-
Initialize npm: Create a
package.json
file.npm init -y
-
Install Dependencies: Install Express, Axios, and dotenv.
npm install express axios dotenv
(Optional: If using yarn, use
yarn add express axios dotenv
) -
Install Dev Dependency (Optional but Recommended): Install
nodemon
for automatic server restarts during development.npm install --save-dev nodemon
(Optional:
yarn add --dev nodemon
) -
Create Project Structure: Set up a basic folder structure for better organization.
-
node-messagebird-whatsapp/
src/
controllers/
messageController.js
routes/
messageRoutes.js
services/
messagebirdService.js
utils/
verifyWebhook.js
app.js
.env
.gitignore
package.json
-
controllers
: Handle request logic. -
routes
: Define API endpoints. -
services
: Encapsulate third-party API interactions (MessageBird). -
utils
: Helper functions (like webhook verification). -
app.js
: Main application entry point. -
.env
: Store environment variables (API keys, etc.). -
.gitignore
: Specify intentionally untracked files that Git should ignore.
-
-
Create
.gitignore
: Create a.gitignore
file in the root directory to prevent committing sensitive information and unnecessary files.# .gitignore node_modules/ .env npm-debug.log* yarn-debug.log* yarn-error.log*
-
Create
.env
File: Create a.env
file in the root directory. We'll populate this with credentials obtained from MessageBird later.# .env PORT=3000 MESSAGEBIRD_API_KEY=YOUR_MESSAGEBIRD_LIVE_API_KEY MESSAGEBIRD_WHATSAPP_CHANNEL_ID=YOUR_WHATSAPP_CHANNEL_ID MESSAGEBIRD_WEBHOOK_SIGNING_KEY=YOUR_WEBHOOK_SIGNING_KEY
Explanation:
PORT
: The port your Express server will listen on.MESSAGEBIRD_API_KEY
: Your live API key from the MessageBird dashboard. Treat this like a password.MESSAGEBIRD_WHATSAPP_CHANNEL_ID
: The unique ID of your configured WhatsApp channel in MessageBird.MESSAGEBIRD_WEBHOOK_SIGNING_KEY
: The secret key provided by MessageBird to verify incoming webhooks. Treat this like a password.
-
Configure
package.json
Scripts: Add scripts to yourpackage.json
for starting the server easily.// package.json (partial) { ""scripts"": { ""start"": ""node src/app.js"", ""dev"": ""nodemon src/app.js"" } }
Now you can run
npm run dev
for development (usesnodemon
) ornpm start
to run the application normally.
2. Implementing Core Functionality
We'll start by setting up the Express server and then implement the logic for sending and receiving messages.
-
Set up Basic Express Server (
src/app.js
):// src/app.js require('dotenv').config(); // Load environment variables from .env file const express = require('express'); const messageRoutes = require('./routes/messageRoutes'); const app = express(); const port = process.env.PORT || 3000; // Middleware to parse raw body for webhook verification // IMPORTANT: This needs to be BEFORE express.json() for the webhook route app.use('/webhook', express.raw({ type: 'application/json' })); // Middleware to parse JSON bodies for other routes app.use(express.json()); // Mount the message routes app.use('/', messageRoutes); // Basic health check endpoint app.get('/health', (req, res) => { res.status(200).send('OK'); }); // Global error handler (basic example) app.use((err, req, res, next) => { console.error('Unhandled error:', err); res.status(500).send('Something broke!'); }); app.listen(port, () => { console.log(`Server listening on port ${port}`); });
Why
express.raw
beforeexpress.json
? Webhook signature verification requires the raw, unparsed request body.express.json()
consumes the body stream, making it unavailable later. We applyexpress.raw
only to the/webhook
path. Other paths needexpress.json()
which should be applied globally or to specific routes after the raw middleware for the webhook. -
Implement MessageBird Service (
src/services/messagebirdService.js
): This service will encapsulate all interactions with the MessageBird API.// src/services/messagebirdService.js const axios = require('axios'); const MESSAGEBIRD_API_ENDPOINT = 'https://conversations.messagebird.com/v1'; const messagebirdClient = axios.create({ baseURL: MESSAGEBIRD_API_ENDPOINT, headers: { 'Authorization': `AccessKey ${process.env.MESSAGEBIRD_API_KEY}`, 'Content-Type': 'application/json', } }); /** * Sends a WhatsApp message via MessageBird Conversations API. * Uses the /conversations/start endpoint which handles finding or creating * a conversation. * @param {string} to - Recipient's phone number (E.164 format). * @param {string} text - The message text content. * @returns {Promise<object>} - The response data from MessageBird API. */ const sendWhatsAppMessage = async (to, text) => { try { const payload = { to: to, type: 'text', content: { text: text }, channelId: process.env.MESSAGEBIRD_WHATSAPP_CHANNEL_ID }; console.log('Sending message via MessageBird:', JSON.stringify(payload, null, 2)); // Using /conversations/start simplifies sending; MessageBird handles // checking if a conversation exists or creating a new one. const response = await messagebirdClient.post('/conversations/start', payload); console.log('MessageBird API Response:', response.data); return response.data; } catch (error) { console.error('Error sending MessageBird message:', error.response ? error.response.data : error.message); // Re-throw the error to be handled by the controller throw error; } }; module.exports = { sendWhatsAppMessage, };
Why
/conversations/start
? This MessageBird endpoint is convenient as it either starts a new conversation or adds the message to an existing one based on the recipient and channel ID, reducing the logic needed in our application. -
Implement Webhook Verification Utility (
src/utils/verifyWebhook.js
): This function verifies the signature of incoming webhooks from MessageBird.// src/utils/verifyWebhook.js const crypto = require('crypto'); /** * Verifies the signature of an incoming MessageBird webhook request. * @param {Buffer} rawBody - The raw request body buffer. * @param {string} signatureHeader - The value of the 'MessageBird-Signature' header. * @param {string} timestampHeader - The value of the 'MessageBird-Request-Timestamp' header. * @param {string} signingKey - Your MessageBird webhook signing key. * @returns {boolean} - True if the signature is valid, false otherwise. */ const verifyMessageBirdWebhook = (rawBody, signatureHeader, timestampHeader, signingKey) => { if (!rawBody || !signatureHeader || !timestampHeader || !signingKey) { console.warn('Webhook verification missing required parameters.'); return false; } try { // MessageBird uses `MessageBird-Signature` (sig) and `MessageBird-Request-Timestamp` (ts). // The signature is calculated over `timestamp.body`. const signedPayload = `${timestampHeader}.${rawBody.toString('utf8')}`; const expectedSignature = crypto .createHmac('sha256', signingKey) .update(signedPayload) .digest('hex'); // Ensure the provided signature is treated as hex const providedSignatureBuffer = Buffer.from(signatureHeader, 'hex'); const expectedSignatureBuffer = Buffer.from(expectedSignature, 'hex'); // Handle potential length differences before comparison if (providedSignatureBuffer.length !== expectedSignatureBuffer.length) { console.warn('Webhook signature length mismatch.'); return false; } // Constant-time comparison to prevent timing attacks const isValid = crypto.timingSafeEqual(providedSignatureBuffer, expectedSignatureBuffer); if (!isValid) { console.warn('Webhook signature mismatch.', { received: signatureHeader, expected: expectedSignature }); } return isValid; } catch (error) { console.error('Error during webhook signature verification:', error); return false; } }; module.exports = { verifyMessageBirdWebhook, };
Why
crypto.timingSafeEqual
? Using a simple===
comparison for signatures can be vulnerable to timing attacks.timingSafeEqual
performs the comparison in constant time, mitigating this risk. -
Implement Message Controller (
src/controllers/messageController.js
): This handles the logic for both the API endpoint (sending) and the webhook (receiving).// src/controllers/messageController.js const messagebirdService = require('../services/messagebirdService'); const { verifyMessageBirdWebhook } = require('../utils/verifyWebhook'); // Controller for the manual send API endpoint const sendManualMessage = async (req, res, next) => { const { to, text } = req.body; // Basic validation if (!to || !text) { return res.status(400).json({ error: 'Missing required fields: ""to"" and ""text"".' }); } if (!process.env.MESSAGEBIRD_WHATSAPP_CHANNEL_ID) { console.error('WhatsApp Channel ID is not configured in .env'); return res.status(500).json({ error: 'Server configuration error.' }); } try { const result = await messagebirdService.sendWhatsAppMessage(to, text); res.status(200).json({ success: true, messageId: result.id, status: result.status }); } catch (error) { // Logged in the service, pass to global error handler or send specific response res.status(500).json({ success: false, error: 'Failed to send message via MessageBird.' }); } }; // Controller for the MessageBird Webhook const handleWebhook = async (req, res, next) => { // 1. Verify Signature const signature = req.headers['messagebird-signature']; const timestamp = req.headers['messagebird-request-timestamp']; const signingKey = process.env.MESSAGEBIRD_WEBHOOK_SIGNING_KEY; // IMPORTANT: Use the raw body stored by the middleware // req.body will be a Buffer here because of `express.raw` on the /webhook route const rawBody = req.body; if (!(rawBody instanceof Buffer)) { console.error('Webhook error: Raw body not available. Check middleware order.'); return res.status(500).send('Internal Server Error: Invalid body parser configuration.'); } if (!verifyMessageBirdWebhook(rawBody, signature, timestamp, signingKey)) { console.warn('Webhook signature verification failed.'); return res.status(403).send('Forbidden: Invalid signature.'); } console.log('Webhook signature verified successfully.'); // 2. Parse the JSON body (now that signature is verified) let payload; try { payload = JSON.parse(rawBody.toString('utf8')); console.log('Received webhook payload:', JSON.stringify(payload, null, 2)); } catch (e) { console.error('Failed to parse webhook JSON:', e); return res.status(400).send('Bad Request: Invalid JSON.'); } // 3. Process the message (Example: Echo Bot) // Check if it's an incoming message event and has text content if (payload.type === 'message.created' && payload.message?.direction === 'received' && payload.message?.type === 'text') { const sender = payload.message.from; const receivedText = payload.message.content.text; const conversationId = payload.conversation.id; // Use conversation ID for replies console.log(`Received text message ""${receivedText}"" from ${sender} in conversation ${conversationId}`); // Simple Echo: Send the same text back const replyText = `You said: ${receivedText}`; try { // Note: We send back to the 'sender' number directly. MessageBird handles routing it // within the correct conversation context based on channelId and sender. await messagebirdService.sendWhatsAppMessage(sender, replyText); console.log(`Sent echo reply to ${sender}`); } catch (error) { console.error(`Failed to send echo reply to ${sender}:`, error); // Don't send error back to MessageBird here, just log it. // Sending 500 might cause MessageBird to retry the webhook unnecessarily. } } else { console.log('Webhook received, but not a processable text message:', payload.type, payload.message?.type); } // 4. Acknowledge receipt to MessageBird // It's crucial to send a 200 OK quickly to prevent retries. res.status(200).send('OK'); }; module.exports = { sendManualMessage, handleWebhook, };
-
Define Routes (
src/routes/messageRoutes.js
): Connect the URL paths to the controller functions.// src/routes/messageRoutes.js const express = require('express'); const messageController = require('../controllers/messageController'); const router = express.Router(); // Endpoint to manually trigger sending a WhatsApp message // POST /send-whatsapp // Body: { ""to"": ""E.164_phone_number"", ""text"": ""Your message content"" } router.post('/send-whatsapp', messageController.sendManualMessage); // Endpoint for MessageBird to POST webhook events // POST /webhook router.post('/webhook', messageController.handleWebhook); module.exports = router;
3. Building a Complete API Layer
Our current API layer is simple, consisting of the /send-whatsapp
endpoint.
- Authentication/Authorization: For this example, the endpoint is unprotected. In a production scenario, you would add middleware here to protect it (e.g., API keys, JWT tokens, OAuth) to ensure only authorized clients can trigger messages.
// Example placeholder for auth middleware (in routes/messageRoutes.js) // const { authenticateApiKey } = require('../middleware/auth'); // router.post('/send-whatsapp', authenticateApiKey, messageController.sendManualMessage);
- Request Validation: We have basic validation in the controller. For more complex validation (data types, formats, lengths), use libraries like
joi
orexpress-validator
.// Example using express-validator (install it first: npm install express-validator) // const { body, validationResult } = require('express-validator'); // router.post('/send-whatsapp', // body('to').isMobilePhone('any', { strictMode: true }).withMessage('Invalid phone number format (E.164 required)'), // body('text').isString().notEmpty().withMessage('Text content cannot be empty'), // (req, res, next) => { // const errors = validationResult(req); // if (!errors.isEmpty()) { // return res.status(400).json({ errors: errors.array() }); // } // next(); // Proceed to controller if validation passes // }, // messageController.sendManualMessage // );
- API Endpoint Documentation (
/send-whatsapp
):- Method:
POST
- URL:
/send-whatsapp
- Body (JSON):
{ ""to"": ""+14155552671"", ""text"": ""Hello from our Node.js App!"" }
- Success Response (200 OK):
{ ""success"": true, ""messageId"": ""mb_message_id_string"", ""status"": ""accepted"" }
- Error Response (400 Bad Request - Validation):
Or with express-validator:
{ ""error"": ""Missing required fields: \""to\"" and \""text\""."" }
{ ""errors"": [ { ""type"": ""field"", ""value"": """", ""msg"": ""Text content cannot be empty"", ""path"": ""text"", ""location"": ""body"" } ] }
- Error Response (500 Internal Server Error - API Failure):
{ ""success"": false, ""error"": ""Failed to send message via MessageBird."" }
- Method:
- Testing with
curl
: Replace placeholders with your actual recipient number and message. Make sure your server is running (npm run dev
).curl -X POST http://localhost:3000/send-whatsapp \ -H ""Content-Type: application/json"" \ -d '{ ""to"": ""+1xxxxxxxxxx"", ""text"": ""Test message from curl!"" }'
4. Integrating with MessageBird (Credentials & Configuration)
This section details how to get the necessary credentials from the MessageBird Dashboard.
-
Get MessageBird API Key:
- Log in to your MessageBird Dashboard.
- Navigate to Developers (usually in the left sidebar) -> API access.
- Under ""Live API Key"", click Show key. Copy this value.
- Paste this value into your
.env
file forMESSAGEBIRD_API_KEY
.
-
Get WhatsApp Channel ID:
- In the MessageBird Dashboard, navigate to Channels (left sidebar).
- Click on your configured WhatsApp channel.
- On the channel's configuration page, find the Channel ID (it's a long alphanumeric string). Copy this value.
- Paste this value into your
.env
file forMESSAGEBIRD_WHATSAPP_CHANNEL_ID
.
-
Get Webhook Signing Key:
- In the MessageBird Dashboard, navigate to Developers -> Webhooks.
- Click Add webhook. If you already have one for Conversations API, click Edit.
- Under the Signing Key section, you'll find the key. If it's your first time, you might need to generate one. Copy this value.
- Paste this value into your
.env
file forMESSAGEBIRD_WEBHOOK_SIGNING_KEY
.
-
Configure Webhook URL in MessageBird:
- While still in the Webhook settings (Developers -> Webhooks):
- URL: You need a publicly accessible URL. During development, use
ngrok
.- Install
ngrok
: https://ngrok.com/download - Run
ngrok http 3000
(or your app's port) in a separate terminal. - Copy the
https://
forwarding URL provided by ngrok (e.g.,https://<random-string>.ngrok.io
). - Paste this URL into the MessageBird webhook configuration, adding
/webhook
at the end (e.g.,https://<random-string>.ngrok.io/webhook
). - Remember, ngrok creates a temporary URL and is suitable only for development and testing. For production, you need to deploy your application to a server with a stable, permanent public HTTPS URL (e.g., via a PaaS like Heroku/Render or your own server with a domain name).
- Install
- Events: Ensure ""Listen for Conversation API events"" is checked, or select specific events like
message.created
andmessage.updated
. For the echo bot,message.created
is essential. - Save the webhook configuration.
- URL: You need a publicly accessible URL. During development, use
- While still in the Webhook settings (Developers -> Webhooks):
-
Environment Variables Handling:
- We use the
dotenv
package, loaded at the very top ofsrc/app.js
(require('dotenv').config();
). - Access variables using
process.env.VARIABLE_NAME
(e.g.,process.env.MESSAGEBIRD_API_KEY
). - Security: The
.env
file should never be committed to version control (ensure it's in.gitignore
). In production environments (like Heroku, AWS, Docker), these variables should be set directly as environment variables on the platform, not via a.env
file.
- We use the
-
Fallback Mechanisms:
- The current
messagebirdService.js
includes atry...catch
block. If the MessageBird API call fails, it logs the error and throws it, allowing the controller to send a 500 response for the/send-whatsapp
endpoint. - For critical notifications, you might implement a retry mechanism (see Section 5) or a fallback channel (e.g., attempt SMS if WhatsApp fails, though this adds complexity).
- The current
5. Error Handling, Logging, and Retry Mechanisms
Production applications require robust error handling and logging.
- Consistent Error Strategy:
- Service Layer (
messagebirdService.js
): Catches specific API call errors, logs detailed information (includingerror.response?.data
from Axios for API error messages), and re-throws the error. - Controller Layer (
messageController.js
): Catches errors from the service layer. For API endpoints (/send-whatsapp
), it sends an appropriate HTTP error response (e.g., 500). For webhooks (/webhook
), it logs the error but still tries to send a 200 OK back to MessageBird to prevent unnecessary retries unless it's a fatal error like signature failure (403) or bad JSON (400). - Global Error Handler (
app.js
): A final catch-all for unexpected synchronous or asynchronous errors passed vianext(err)
. Logs the error and sends a generic 500 response.
- Service Layer (
- Logging:
- Currently using
console.log
andconsole.error
. This is acceptable for basic examples but insufficient for production. - Recommendation: Use a dedicated logging library like Winston or Pino. These enable:
- Different log levels (debug, info, warn, error).
- Structured logging (JSON format, easier for machines to parse).
- Multiple transports (log to console, files, external logging services like Datadog, Logstash).
- Example (Conceptual with Winston):
// src/utils/logger.js (Example) const winston = require('winston'); const logger = winston.createLogger({ level: process.env.LOG_LEVEL || 'info', format: winston.format.json(), transports: [ new winston.transports.Console({ format: winston.format.simple() }), // Add file or other transports here for production ], }); module.exports = logger; // In other files: // const logger = require('./utils/logger'); // logger.info('Message sent successfully.'); // logger.error('Failed to send message:', { error: err.message });
- Currently using
- Retry Mechanisms:
- Network issues or temporary service outages can cause API calls to fail. Implementing retries can improve reliability.
- Strategy: Use exponential backoff – wait longer between each retry attempt.
- Implementation:
- Manually implement a loop with
setTimeout
. - Use a library like
axios-retry
which automatically handles retries for Axios requests based on configuration (e.g., retry count, status codes to retry on, backoff delay).
- Manually implement a loop with
- Example (Conceptual with
axios-retry
- install it:npm install axios-retry
):// src/services/messagebirdService.js (Modified) const axios = require('axios'); const axiosRetry = require('axios-retry').default; // Use .default for CJS require const MESSAGEBIRD_API_ENDPOINT = 'https://conversations.messagebird.com/v1'; const messagebirdClient = axios.create(/* ... as before ... */); // Apply retry logic to the axios instance axiosRetry(messagebirdClient, { retries: 3, // Number of retry attempts retryDelay: (retryCount) => { console.log(`Retry attempt: ${retryCount}`); return retryCount * 1000; // Exponential backoff (1s, 2s, 3s) }, retryCondition: (error) => { // Retry on network errors or specific server errors (e.g., 5xx) return axiosRetry.isNetworkOrIdempotentRequestError(error) || error.response?.status >= 500; }, }); // ... rest of the service file ...
- Testing Error Scenarios:
- Temporarily use an invalid API key in
.env
to test authentication errors. - Provide an invalid phone number format to
/send-whatsapp
to test validation errors. - Disconnect your network temporarily to test network errors (if using retries).
- Send an invalid payload structure to MessageBird (modify
messagebirdService.js
) to test API validation errors. - Tamper with the signature or timestamp in a simulated webhook request (using Postman/curl) to test webhook verification failure.
- Temporarily use an invalid API key in
- Log Analysis: In production, use log aggregation tools (ELK stack, Datadog, Splunk) to search, filter, and analyze logs from your application to quickly identify and diagnose errors. Structured logging (JSON) is crucial for this.
6. Database Schema and Data Layer
This simple echo bot does not require a database. However, in a more complex application, you would likely need one to store:
- Conversation History: Log incoming/outgoing messages, timestamps, statuses.
- User Data: Link WhatsApp numbers to user accounts in your system, store preferences, state (for chatbots).
- Message Status: Track MessageBird message status updates (sent, delivered, read) received via webhooks.
Considerations:
- Schema Design (Conceptual):
conversations
table (conversation_id (PK), user_id (FK), channel_id, started_at)messages
table (message_id (PK), conversation_id (FK), messagebird_message_id, direction (in/out), content, type, status, timestamp)users
table (user_id (PK), whatsapp_number, name, etc.)- (An Entity Relationship Diagram would be beneficial here)
- Data Access: Use an Object-Relational Mapper (ORM) like Prisma or Sequelize to interact with the database safely and efficiently.
- Prisma: Modern, type-safe ORM. Define schema in
schema.prisma
, runnpx prisma migrate dev
to create/update DB tables, use Prisma Client for queries. - Sequelize: Mature, feature-rich ORM. Define models in JavaScript, use migrations for schema changes.
- Prisma: Modern, type-safe ORM. Define schema in
- Performance: Index frequently queried columns (e.g.,
whatsapp_number
,conversation_id
,timestamp
). Use efficient queries. Consider database connection pooling. - Data Population: Use migration scripts or seed scripts (often provided by ORMs) to populate initial data if needed.
Example (Conceptual Prisma Schema):
// prisma/schema.prisma
datasource db {
provider = ""postgresql"" // or mysql, sqlite
url = env(""DATABASE_URL"")
}
generator client {
provider = ""prisma-client-js""
}
// Define your models below (example structure)
// model User { ... }
// model Conversation { ... }
// model Message { ... }