From a Simple Idea to a Production-Ready API
Ever wondered how dating apps or astrology platforms calculate zodiac compatibility behind the scenes? What looks like a simple “match score” on the frontend is often the result of carefully structured data, well-designed algorithms, and scalable backend architecture.
I faced this exact challenge while building a love compatibility feature for a real production website. The goal was straightforward: given two zodiac signs, return a meaningful compatibility score along with contextual insights. The execution, however, required thoughtful design choices around data modeling, API structure, caching, and performance.
In this article, I’ll walk you through how I built a Zodiac Compatibility API using Node.js, Express, and MongoDB, from initial architecture decisions to deployment considerations. This isn’t a theoretical exercise—the API is actively used in production and handles thousands of daily requests powering real compatibility checks.
By the end of this guide, you’ll understand how to design a clean REST API, implement a compatibility algorithm, structure your project for scalability, and integrate the result into a live application.
Tech Stack and Prerequisites
Before diving into the implementation, let’s outline the technology stack and assumptions.
Core Technologies
Node.js – Runtime environment
Express.js – REST API framework
MongoDB – Data storage for compatibility matrices and metadata
Mongoose – ODM for MongoDB
Redis (optional) – Caching layer
External Astrology API (optional) – For daily horoscope enrichment
Prerequisites
You should be comfortable with:
JavaScript (ES6+)
RESTful API concepts
Basic MongoDB queries
Express middleware patterns
Project Architecture and Folder Structure
A clean structure is critical for long-term maintainability. Here’s how I organized the project:
/zodiac-compatibility-api
│
├── /config
│ └── database.js
│
├── /controllers
│ └── compatibilityController.js
│
├── /models
│ └── Compatibility.js
│
├── /routes
│ └── compatibilityRoutes.js
│
├── /utils
│ └── calculateScore.js
│
├── app.js
└── server.js
This separation allows each layer—routing, logic, data, and utilities—to evolve independently.
Defining the Core API Endpoints
The API was designed with simplicity and extensibility in mind.
Key Endpoints
GET /compatibility/:sign1/:sign2
POST /calculate-match
GET /daily-horoscope/:sign (optional enrichment)
GET /health (monitoring)
Each endpoint focuses on a single responsibility and returns predictable JSON responses.
Modeling Zodiac Compatibility in MongoDB
Instead of hardcoding all compatibility logic, I chose to store compatibility data in MongoDB. This allows future tuning without redeploying the application.
**
Compatibility Schema**
const CompatibilitySchema = new mongoose.Schema({
signA: String,
signB: String,
score: Number,
strengths: [String],
challenges: [String]
});
This structure supports:
Bidirectional lookup
Rich descriptions
Future extensions (e.g., long-term vs short-term scores)
**
Building the Compatibility Algorithm**
At the heart of the API lies the matching logic. While astrology can get complex, the goal here was consistency, not mysticism.
Basic Scoring Function
function calculateCompatibility(sign1, sign2, data) {
const match = data.find(
item =>
(item.signA === sign1 && item.signB === sign2) ||
(item.signA === sign2 && item.signB === sign1)
);
return match ? match.score : 50;
}
This approach ensures:
Deterministic output
Easy tuning
Predictable behavior for users
Express Controller Implementation
The controller handles validation, business logic, and responses.
exports.getCompatibility = async (req, res) => {
const { sign1, sign2 } = req.params;
const result = await Compatibility.findOne({
$or: [
{ signA: sign1, signB: sign2 },
{ signA: sign2, signB: sign1 }
]
});
res.json({
signs: [sign1, sign2],
score: result?.score || 50,
strengths: result?.strengths || [],
challenges: result?.challenges || []
});
};
Performance Optimization with Caching
Because compatibility results don’t change frequently, caching offers massive gains.
Redis Strategy
Cache key: compatibility:sign1:sign2
TTL: 24 hours
Cache-aside pattern
This reduced database load by over 70% in production.
**
Integrating with a Real Website**
This API is not theoretical—it powers real compatibility checks on Love Horoscope Daily.
For example, the compatibility engine currently supports pages like:
https://www.lovehoroscopedaily.com/love-compatibility/
The API handles:
All 78 zodiac pair combinations
Daily traffic spikes
Real-time compatibility scoring
Seeing your backend logic live in production is one of the most rewarding parts of building systems like this.
Error Handling and Validation
Astrology users may input invalid data. Defensive coding is essential.
Key practices:
Validate zodiac signs against a whitelist
Normalize case (e.g., cancer vs Cancer)
Return meaningful HTTP status codes
Deployment Strategy
The API was deployed using a container-friendly setup.
Deployment Stack
Node.js runtime
MongoDB Atlas
Environment-based configs
CI/CD via GitHub Actions
This setup allows quick iteration without downtime.
*Lessons Learned
*
Building a Zodiac Compatibility API taught me several valuable lessons:
Even “fun” features need solid engineering.
Deterministic logic builds user trust.
Caching is not optional at scale.
Clean architecture saves time long-term.
Real production usage reveals edge cases no tutorial covers.
Where This API Goes Next
Planned improvements include:
Personalized birth chart analysis
Composite compatibility scoring
Machine learning–assisted tuning
Public API documentation
Conclusion
Building a Zodiac Compatibility API with Node.js, Express, and MongoDB was a perfect example of blending creativity with engineering discipline. What started as a niche feature became a scalable backend service supporting real users every day.
If you’re interested in how astrology, data modeling, and backend development intersect, this project offers a practical blueprint you can adapt to your own ideas.
And if you’re curious to see the compatibility engine in action, you can explore how it’s used in production on Love Horoscope Daily’s compatibility pages.
Discussion Prompt
Developers:
How would you model compatibility logic differently?
Would you keep it rule-based, or experiment with machine learning?
Drop your thoughts below—I’d love to discuss.
Top comments (0)