Serverless is the natural architecture for astrology APIs. Horoscope requests are bursty — they spike on mornings, weekends, eclipse events, and festival seasons — then drop to near-zero during quiet hours. Running a persistent EC2 instance to handle this pattern wastes money. AWS Lambda, combined with Vedika API's 140+ calculation endpoints, lets you build production-grade astrology backends that cost almost nothing at low traffic and scale automatically to handle millions of requests.
In this guide, we'll deploy a complete serverless astrology backend using the Serverless Framework, integrate Vedika API for planetary calculations and AI-powered predictions, cache responses in DynamoDB, and monitor everything with CloudWatch. By the end, you'll have a production-ready system deployable to any AWS account in under 30 minutes.
What You'll Build: A serverless astrology API with AWS Lambda functions for birth chart generation, daily horoscopes, and AI-powered queries. DynamoDB caching reduces Vedika API calls by 80%+. API Gateway handles authentication, throttling, and CORS. CloudWatch dashboards monitor latency and error rates in real time.
Architecture Overview
Client Request
→ API Gateway (REST API + API Key Auth)
→ Lambda: birthChartHandler → DynamoDB Cache → Vedika API
→ Lambda: horoscopeHandler → DynamoDB Cache → Vedika API
→ Lambda: aiQueryHandler → DynamoDB Cache → Vedika API
→ CloudWatch Logs + Metrics
→ SNS Alert on Error Rate > 1%
Zero Idle Cost
Lambda charges only per invocation. No requests = $0.00. Perfect for apps with variable traffic patterns.
Auto-Scaling
Handles 1 request or 10,000 concurrent requests without configuration. AWS manages scaling automatically.
DynamoDB Caching
Birth charts are deterministic. Cache once, serve forever. Reduces Vedika API spend by 70-90%.
Native AWS Integration
Secrets Manager for API keys, CloudWatch for monitoring, API Gateway for rate limiting and auth.
Step 1: Project Setup with Serverless Framework
Install the Serverless Framework and create a new project:
npm install -g serverless
serverless create --template aws-nodejs --path astrology-lambda
cd astrology-lambda
npm install axios @aws-sdk/client-dynamodb @aws-sdk/lib-dynamodb
npm install --save-dev serverless-offline serverless-dotenv-plugin
serverless.yml Configuration
Configure your Serverless service with all three Lambda functions, DynamoDB table, and API Gateway:
service: vedika-astrology-api
frameworkVersion: '3'
provider:
name: aws
runtime: nodejs20.x
region: us-east-1
memorySize: 256
timeout: 30
environment:
VEDIKA_API_KEY: '${ssm:/vedika/api-key}'
CACHE_TABLE: '${self:service}-cache-${sls:stage}'
VEDIKA_BASE_URL: 'https://api.vedika.io'
iam:
role:
statements:
- Effect: Allow
Action:
- dynamodb:GetItem
- dynamodb:PutItem
- dynamodb:DeleteItem
Resource: 'arn:aws:dynamodb:${aws:region}:*:table/${self:provider.environment.CACHE_TABLE}'
functions:
birthChart:
handler: src/handlers/birthChart.handler
description: Generate Vedic birth chart via Vedika API
events:
- http:
path: /birth-chart
method: post
cors: true
private: true
reservedConcurrency: 50
horoscope:
handler: src/handlers/horoscope.handler
description: Daily/weekly/monthly horoscope predictions
events:
- http:
path: /horoscope/{period}/{sign}
method: get
cors: true
private: true
reservedConcurrency: 100
aiQuery:
handler: src/handlers/aiQuery.handler
description: AI-powered natural language astrology queries
timeout: 60
memorySize: 512
events:
- http:
path: /query
method: post
cors: true
private: true
reservedConcurrency: 30
resources:
Resources:
AstrologyCache:
Type: AWS::DynamoDB::Table
Properties:
TableName: '${self:provider.environment.CACHE_TABLE}'
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: cacheKey
AttributeType: S
KeySchema:
- AttributeName: cacheKey
KeyType: HASH
TimeToLiveSpecification:
AttributeName: ttl
Enabled: true
plugins:
- serverless-offline
- serverless-dotenv-plugin
Step 2: DynamoDB Cache Layer
Create a reusable cache module that all Lambda handlers will share. Birth charts are deterministic — the same birth data always produces the same planetary positions, making caching extremely effective:
const { DynamoDBClient } = require('@aws-sdk/client-dynamodb');
const { DynamoDBDocumentClient, GetCommand, PutCommand } = require('@aws-sdk/lib-dynamodb');
const crypto = require('crypto');
const client = new DynamoDBClient({});
const dynamo = DynamoDBDocumentClient.from(client);
const TABLE = process.env.CACHE_TABLE;
function makeCacheKey(prefix, params) {
const hash = crypto
.createHash('sha256')
.update(JSON.stringify(params))
.digest('hex')
.substring(0, 16);
return `${prefix}:${hash}`;
}
async function getCached(key) {
try {
const result = await dynamo.send(new GetCommand({
TableName: TABLE,
Key: { cacheKey: key }
}));
if (result.Item && result.Item.data) {
return JSON.parse(result.Item.data);
}
} catch (e) {
console.warn('Cache read error:', e.message);
}
return null;
}
async function setCached(key, data, ttlSeconds = 86400) {
try {
await dynamo.send(new PutCommand({
TableName: TABLE,
Item: {
cacheKey: key,
data: JSON.stringify(data),
ttl: Math.floor(Date.now() / 1000) + ttlSeconds,
cachedAt: new Date().toISOString()
}
}));
} catch (e) {
console.warn('Cache write error:', e.message);
}
}
module.exports = { makeCacheKey, getCached, setCached };
Step 3: Birth Chart Lambda Handler
The birth chart handler generates complete Vedic birth charts using Vedika API's Swiss Ephemeris-powered calculation engine, with DynamoDB caching for repeat requests:
const axios = require('axios');
const { makeCacheKey, getCached, setCached } = require('../utils/cache');
const VEDIKA_BASE = process.env.VEDIKA_BASE_URL;
const API_KEY = process.env.VEDIKA_API_KEY;
const vedika = axios.create({
baseURL: VEDIKA_BASE,
headers: {
'X-API-Key': API_KEY,
'Content-Type': 'application/json'
},
timeout: 25000
});
module.exports.handler = async (event) => {
const startTime = Date.now();
let body;
try {
body = JSON.parse(event.body || '{}');
} catch {
return { statusCode: 400, body: JSON.stringify({ error: 'Invalid JSON body' }) };
}
const { datetime, latitude, longitude, timezone = '+05:30', language = 'en' } = body;
if (!datetime || latitude === undefined || longitude === undefined) {
return {
statusCode: 400,
body: JSON.stringify({ error: 'datetime, latitude, longitude are required' })
};
}
const cacheKey = makeCacheKey('chart', { datetime, latitude, longitude, timezone, language });
const cached = await getCached(cacheKey);
if (cached) {
return {
statusCode: 200,
headers: { 'X-Cache': 'HIT', 'Access-Control-Allow-Origin': '*' },
body: JSON.stringify(cached)
};
}
try {
const response = await vedika.post('/v2/astrology/birth-chart', {
datetime, latitude, longitude, timezone, language
});
const result = {
...response.data,
meta: {
computedAt: new Date().toISOString(),
latencyMs: Date.now() - startTime,
source: 'vedika-api'
}
};
await setCached(cacheKey, result, 30 * 24 * 3600);
return {
statusCode: 200,
headers: { 'X-Cache': 'MISS', 'Access-Control-Allow-Origin': '*' },
body: JSON.stringify(result)
};
} catch (err) {
console.error('Vedika API error:', err.response?.data || err.message);
return {
statusCode: err.response?.status || 502,
body: JSON.stringify({ error: err.response?.data?.error || 'Upstream error' })
};
}
};
Step 4: Daily Horoscope Handler with 24h Cache
Daily horoscopes are sign-specific and change every day — cache them with a 24-hour TTL, keyed by sign + date:
const axios = require('axios');
const { getCached, setCached } = require('../utils/cache');
const vedika = axios.create({
baseURL: process.env.VEDIKA_BASE_URL,
headers: { 'X-API-Key': process.env.VEDIKA_API_KEY },
timeout: 15000
});
const VALID_PERIODS = ['daily', 'weekly', 'monthly'];
const VALID_SIGNS = [
'aries', 'taurus', 'gemini', 'cancer',
'leo', 'virgo', 'libra', 'scorpio',
'sagittarius', 'capricorn', 'aquarius', 'pisces'
];
module.exports.handler = async (event) => {
const { period, sign } = event.pathParameters || {};
const lang = event.queryStringParameters?.lang || 'en';
if (!VALID_PERIODS.includes(period) || !VALID_SIGNS.includes(sign?.toLowerCase())) {
return { statusCode: 400, body: JSON.stringify({ error: 'Invalid period or sign' }) };
}
const today = new Date().toISOString().split('T')[0];
const cacheKey = `horoscope:${period}:${sign}:${lang}:${today}`;
const cached = await getCached(cacheKey);
if (cached) {
return {
statusCode: 200,
headers: { 'X-Cache': 'HIT', 'Cache-Control': 'public, max-age=3600', 'Access-Control-Allow-Origin': '*' },
body: JSON.stringify(cached)
};
}
try {
const endpoint = `/v2/astrology/horoscope-${period}`;
const response = await vedika.post(endpoint, {
sign: sign.toLowerCase(),
language: lang
});
const result = { ...response.data, date: today, sign, period };
const ttlMap = { daily: 86400, weekly: 604800, monthly: 2592000 };
await setCached(cacheKey, result, ttlMap[period]);
return {
statusCode: 200,
headers: { 'X-Cache': 'MISS', 'Access-Control-Allow-Origin': '*' },
body: JSON.stringify(result)
};
} catch (err) {
return { statusCode: 502, body: JSON.stringify({ error: 'Horoscope generation failed' }) };
}
};
Step 5: AI Query Handler (Natural Language)
Vedika API's AI query endpoint accepts natural language questions — users can ask "When will I get married?" or "Is this a good time to change jobs?" and receive personalized answers based on their birth chart. Unlike competitors, Vedika's AI is built on real Swiss Ephemeris calculations, not guesses:
const axios = require('axis');
const { makeCacheKey, getCached, setCached } = require('../utils/cache');
const vedika = axios.create({
baseURL: process.env.VEDIKA_BASE_URL,
headers: { 'X-API-Key': process.env.VEDIKA_API_KEY },
timeout: 55000
});
module.exports.handler = async (event) => {
const body = JSON.parse(event.body || '{}');
const { question, birthDetails, system = 'vedic', language = 'en' } = body;
if (!question || !birthDetails) {
return { statusCode: 400, body: JSON.stringify({ error: 'question and birthDetails required' }) };
}
const cacheKey = makeCacheKey('ai', { question, birthDetails, system, language });
const cached = await getCached(cacheKey);
if (cached) {
return {
statusCode: 200,
headers: { 'X-Cache': 'HIT', 'Access-Control-Allow-Origin': '*' },
body: JSON.stringify(cached)
};
}
try {
const response = await vedika.post('/api/v1/astrology/query', {
question,
birthDetails: {
datetime: birthDetails.datetime,
latitude: birthDetails.latitude,
longitude: birthDetails.longitude,
timezone: birthDetails.timezone || '+05:30'
},
system,
language
});
const result = response.data;
await setCached(cacheKey, result, 3600);
return {
statusCode: 200,
headers: { 'X-Cache': 'MISS', 'Access-Control-Allow-Origin': '*' },
body: JSON.stringify(result)
};
} catch (err) {
console.error('AI query error:', err.response?.data);
return { statusCode: 502, body: JSON.stringify({ error: 'AI query failed' }) };
}
};
Step 6: Store API Key in AWS Secrets Manager
Never hardcode your Vedika API key in Lambda environment variables — use AWS Secrets Manager for rotation support and audit trails:
aws ssm put-parameter \
--name "/vedika/api-key" \
--value "vk_live_YOUR_KEY_HERE" \
--type SecureString \
--region us-east-1
aws ssm get-parameter --name "/vedika/api-key" --with-decryption
Step 7: Deploy and Test
serverless deploy --stage prod
curl -X POST https://abc123.execute-api.us-east-1.amazonaws.com/prod/birth-chart \
-H "x-api-key: YOUR_GATEWAY_KEY" \
-H "Content-Type: application/json" \
-d '{
"datetime": "1990-06-15T10:30:00",
"latitude": 28.6139,
"longitude": 77.2090,
"timezone": "+05:30"
}'
curl https://abc123.execute-api.us-east-1.amazonaws.com/prod/horoscope/daily/aries \
-H "x-api-key: YOUR_GATEWAY_KEY"
curl -X POST https://abc123.execute-api.us-east-1.amazonaws.com/prod/query \
-H "x-api-key: YOUR_GATEWAY_KEY" \
-H "Content-Type: application/json" \
-d '{
"question": "What does my career look like this year?",
"birthDetails": {
"datetime": "1990-06-15T10:30:00",
"latitude": 28.6139,
"longitude": 77.2090,
"timezone": "+05:30"
},
"language": "en"
}'
Ready to Go Serverless?
Get your Vedika API key and deploy this Lambda stack in 30 minutes. Free sandbox for development — no credit card required.
Read the Docs
View Pricing
Step 8: CloudWatch Monitoring
Add a CloudWatch dashboard to track Lambda latency, DynamoDB cache hit rates, and Vedika API error rates. Use a CloudFormation addition to serverless.yml:
AstrologyDashboard:
Type: AWS::CloudWatch::Dashboard
Properties:
DashboardName: astrology-api-${sls:stage}
DashboardBody: |
{
"widgets": [
{
"type": "metric",
"properties": {
"metrics": [
["AWS/Lambda", "Duration", "FunctionName", "vedika-astrology-api-prod-birthChart"],
["AWS/Lambda", "Duration", "FunctionName", "vedika-astrology-api-prod-horoscope"],
["AWS/Lambda", "Duration", "FunctionName", "vedika-astrology-api-prod-aiQuery"]
],
"title": "Lambda P99 Latency",
"stat": "p99",
"period": 300
}
},
{
"type": "metric",
"properties": {
"metrics": [
["AWS/Lambda", "Errors", "FunctionName", "vedika-astrology-api-prod-birthChart"],
["AWS/Lambda", "Errors", "FunctionName", "vedika-astrology-api-prod-horoscope"]
],
"title": "Lambda Error Count",
"stat": "Sum",
"period": 300
}
}
]
}
Cold Start Mitigation
Cold starts add 200-800ms to the first request after inactivity. Three strategies to minimize impact:
- Provisioned Concurrency: Keep 1 warm instance for your birth chart handler (most latency-sensitive). Add to
serverless.yml: provisionedConcurrency: 1 under the function definition.
- Keep packages small: Use
esbuild bundling via serverless-esbuild plugin. Tree-shaking removes unused code, reducing cold start init time by 40-60%.
- Initialize clients outside handler: The axios instance and DynamoDB client are created once at module load, not per-invocation. Warm Lambda instances reuse them without re-initialization.
custom:
esbuild:
bundle: true
minify: true
target: 'node20'
exclude:
- '@aws-sdk/*'
plugins:
- serverless-esbuild
- serverless-offline
Cost Analysis at Scale
10K req/month
Lambda: ~$0.02, DynamoDB: ~$0.01, API GW: ~$0.04. Total AWS: ~$0.07 + Vedika $12/mo.
100K req/month
Lambda: ~$0.21, DynamoDB: ~$0.13, API GW: ~$0.10. Total AWS: ~$0.44 + Vedika $12/mo.
1M req/month
Lambda: ~$2.10, DynamoDB: ~$1.30, API GW: ~$1.00. Total AWS: ~$4.40 + Vedika $60/mo.
With 80% cache hit
DynamoDB cache serves 800K of 1M requests. Vedika API only billed for 200K calls. Significant wallet savings.
Why Vedika API for Serverless Architecture?
Several astrology APIs exist, but Vedika has properties that make it uniquely suited for serverless deployments:
- Stateless REST endpoints: Every Vedika API call is stateless — no sessions, no server affinity. Serverless functions can call from any region, any container, with no coordination needed.
- Predictable response format: Consistent JSON schema across all 140+ endpoints simplifies DynamoDB serialization and client-side parsing.
- Fast P50 latency: Non-AI endpoints (birth chart, panchang, dasha) return in 50-200ms. Your Lambda execution time is dominated by the Vedika call — fast API = low Lambda cost.
- Wallet-based billing: Vedika's credit system means your Lambda can make exactly as many calls as your wallet allows, with clean budget enforcement.
- AI chatbot included: The
/api/v1/astrology/query endpoint handles natural language in 30 languages. No separate NLP service needed — one Lambda call does it all.
Conclusion
AWS Lambda and Vedika API form a natural pairing for production astrology backends. Lambda handles the scaling and cost efficiency; Vedika handles the astronomical accuracy and AI intelligence. With DynamoDB caching achieving 70-90% cache hit rates on birth charts, your effective cost per API call drops dramatically as your user base grows.
Next steps:
- Clone the full serverless template from our documentation
- Get your Vedika API key at vedika.io/dashboard
- Store the key in AWS Parameter Store
- Deploy with
serverless deploy --stage prod
- Add CloudWatch alarms for error rate and latency thresholds
About Vedika Intelligence: Vedika is the only B2B astrology API with AI-powered chatbot capabilities, serving production apps worldwide. Our platform provides 140+ endpoints with Swiss Ephemeris precision, supports 30 languages, and starts at $12/month. The world's first astrology MCP server enables AI agents to query planetary positions and predictions natively.