Designing a Serverless Inquiry System for a Luxury Resort
The Problem
Himalayan Nirvana Resort was getting 50-100 guest inquiries per day through their website contact form. Each inquiry sent an email. Someone manually replied to each one.
As the resort's launch approached, that number was expected to grow 5x. The manual process wasn't scaling. The shared hosting email server had already been flagged for spam twice.
The requirement: build an automated inquiry management system that could scale to 500+ inquiries per day without manual intervention, cost less than $20/month, and integrate with WhatsApp for guest communication.
Enter serverless.
The Architecture
Guest fills inquiry form (Next.js)
|
API Gateway (HTTPS endpoint)
|
Lambda (validate + process)
|
DynamoDB (store inquiry)
|
Lambda (send notifications)
|
SQS (queue for retries)
|
SES (email notification to resort)
SNS (SMS/WhatsApp fallback)
No servers. No maintenance windows. No monthly hosting fees.
Why DynamoDB Instead of RDS
For an inquiry system, the access patterns are simple:
- Write: insert new inquiry
- Read: fetch inquiry by ID
- Scan: list inquiries by date
No complex joins. No relational queries. DynamoDB was the right choice.
const AWS = require('aws-sdk');
const dynamo = new AWS.DynamoDB.DocumentClient();
async function saveInquiry(inquiry: Inquiry) {
await dynamo.put({
TableName: process.env.DYNAMODB_TABLE,
Item: {
id: uuid(),
...inquiry,
createdAt: Date.now(),
status: 'new',
},
}).promise();
}
Cost for 15,000 inquiries/month: approximately $0 (within the free tier).
The Lambda Cold Start Problem
One issue I hit: the inquiry form is used by guests worldwide. A guest from Australia gets a cold start on the Lambda because the function hasn't been invoked in a while. Cold start adds 1-2 seconds to the response time.
Solutions I evaluated:
- Provisioned Concurrency — keeps N instances warm. Costs money but eliminates cold starts.
- Warmer function — a CloudWatch Event that pings the function every 5 minutes. Free but hacky.
- Optimize the function — smaller deployment package, faster runtime.
I went with option 3 first. Reducing the Node.js dependency size from 15MB to 3MB cut cold starts by 60%. If traffic grows, I'll add Provisioned Concurrency.
Cost Projections
At 500 inquiries/day (15,000/month):
API Gateway: ~$1.50/month
Lambda: ~$0.20/month
DynamoDB: ~$0/month (on-demand, within free tier)
SES: ~$0/month (62,000 emails free/month)
SQS: ~$0/month (1 million requests free)
Total: ~$1.70/month
Compare that to a $30/month VPS that handles the same load with more complexity. Or a $200/month SaaS solution.
This is why serverless makes sense for hospitality.
What I Learned Building This
1. Error handling matters more than business logic.
When SES sends a notification to the resort and it bounces, the inquiry shouldn't be lost. I used DynamoDB TTL with a DLQ (Dead Letter Queue) pattern:
Inquiry saved → notification sent → success → mark as notified
↓ failure
SQS DLQ → retry (3 times) → mark as failed
Failed inquiries are still accessible in the admin dashboard. No data loss.
2. Rate limiting at the API Gateway level.
The contact form could be abused. I added usage plans and API keys to API Gateway. Simple throttle at 10 requests per IP per minute.
3. CloudWatch Logs are not a database.
Early on, I relied on CloudWatch for debugging. Searching logs for a specific inquiry was painful. I added structured logging with correlation IDs:
console.log(JSON.stringify({
type: 'inquiry_created',
inquiryId: id,
guestName: name,
source: 'website',
}));
CloudWatch Insights can query these, but DynamoDB is still the source of truth.
What I'd Build Next
- WhatsApp notification integration (already mentioned above — Twilio or WATI)
- Inquiry dashboard for the resort staff to view, filter, and respond
- Auto-reply for common questions (rates, availability, check-in times)
- Analytics — which months get the most inquiries? Which channels?
The Bottom Line
For a resort generating 500 inquiries/month, a serverless architecture costs less than $2/month. It scales to 50,000 inquiries without any architecture changes. It requires zero server management.
If you're running a hospitality business and still using a shared hosting contact form, this is the upgrade.
I'm sharing the detailed architecture because I believe Nepal's hospitality industry needs more tech solutions built for local constraints. This is my contribution.