KLEAR KARMA - SYSTEM ARCHITECTURE & TECHNICAL DOCUMENTATION
Table of Contents
- Architecture Overview
- System Components
- Technology Stack
- Database Design
- API Architecture
- Security Framework
- Scalability & Performance
- DevOps & Infrastructure
- AI/ML Integration
- Mobile Architecture
1. Architecture Overview
1.1 High-Level System Architecture
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PRESENTATION LAYER β
βββββββββββββββββββ¬ββββββββββββββββββ¬ββββββββββββββββββββββββββββββ€
β Web App β Mobile Apps β Admin Dashboard β
β (Next.js) β (React Native)β (React.js) β
βββββββββββββββββββ΄ββββββββββββββββββ΄ββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β API GATEWAY LAYER β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Load Balancer β Rate Limiting β Authentication β Monitoring β
β (Nginx) β (Redis) β (JWT/OAuth) β (DataDog) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β MICROSERVICES LAYER β
βββββββββββββββ¬ββββββββββββββ¬ββββββββββββββ¬ββββββββββββββββββββββ€
β User ServiceβAuth Service βSearch Serviceβ Booking Service β
β (Node.js) β(Node.js) β(Elasticsearch)β (Node.js) β
βββββββββββββββΌββββββββββββββΌββββββββββββββΌββββββββββββββββββββββ€
βPayment Svc βNotification βML/AI Serviceβ Content Service β
β(Node.js) βService β(Python) β (Node.js) β
β β(Node.js) β β β
βββββββββββββββ΄ββββββββββββββ΄ββββββββββββββ΄ββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β DATA LAYER β
βββββββββββββββ¬ββββββββββββββ¬ββββββββββββββ¬ββββββββββββββββββββββ€
β PostgreSQL β Redis βElasticsearchβ File Storage β
β(Primary DB) β (Cache) β (Search) β (AWS S3) β
βββββββββββββββΌββββββββββββββΌββββββββββββββΌββββββββββββββββββββββ€
β MongoDB β InfluxDB β Kafka β CDN β
β(Documents) β(Analytics) β(Streaming) β (CloudFlare) β
βββββββββββββββ΄ββββββββββββββ΄ββββββββββββββ΄ββββββββββββββββββββββ
1.2 Architecture Principles
Core Principles
- Microservices Architecture: Loosely coupled, independently deployable services
- API-First Design: RESTful APIs with GraphQL for complex queries
- Event-Driven Architecture: Asynchronous communication via message queues
- Cloud-Native: Containerized applications with Kubernetes orchestration
- Security by Design: Zero-trust security model with end-to-end encryption
Design Patterns
- CQRS (Command Query Responsibility Segregation): Separate read/write operations
- Event Sourcing: Immutable event logs for audit trails
- Circuit Breaker: Fault tolerance and graceful degradation
- Saga Pattern: Distributed transaction management
- Repository Pattern: Data access abstraction
2. System Components
2.1 Frontend Applications
Web Application (Next.js)
src/
βββ components/
β βββ common/
β βββ forms/
β βββ layout/
β βββ features/
βββ pages/
β βββ api/
β βββ auth/
β βββ dashboard/
β βββ booking/
βββ hooks/
βββ utils/
βββ types/
βββ styles/
Key Features:
- Server-side rendering (SSR) for SEO optimization
- Progressive Web App (PWA) capabilities
- Real-time updates via WebSocket connections
- Responsive design with mobile-first approach
- Accessibility compliance (WCAG 2.1 AA)
Mobile Applications (React Native)
src/
βββ components/
β βββ UI/
β βββ Navigation/
β βββ Features/
βββ screens/
β βββ Auth/
β βββ Home/
β βββ Search/
β βββ Profile/
βββ services/
β βββ api/
β βββ storage/
β βββ notifications/
βββ navigation/
βββ utils/
βββ types/
Platform-Specific Features:
- iOS: HealthKit integration, Apple Pay
- Android: Google Fit integration, Google Pay
- Cross-platform: Biometric authentication, offline mode
2.2 Backend Services
User Service
interface UserService {
createUser(userData: CreateUserDTO): Promise<User>
updateUser(userId: string, updates: UpdateUserDTO): Promise<User>
getUserById(userId: string): Promise<User>
deleteUser(userId: string): Promise<void>
updateProfile(userId: string, profile: ProfileDTO): Promise<Profile>
uploadProfileImage(userId: string, image: File): Promise<string>
initiateVerification(userId: string, type: VerificationType): Promise<void>
completeVerification(userId: string, token: string): Promise<boolean>
}
Authentication Service
interface AuthService {
login(credentials: LoginDTO): Promise<AuthResponse>
register(userData: RegisterDTO): Promise<AuthResponse>
refreshToken(refreshToken: string): Promise<AuthResponse>
logout(userId: string): Promise<void>
googleAuth(token: string): Promise<AuthResponse>
facebookAuth(token: string): Promise<AuthResponse>
resetPassword(email: string): Promise<void>
changePassword(userId: string, passwords: ChangePasswordDTO): Promise<void>
enableTwoFactor(userId: string): Promise<TwoFactorSetup>
}
Booking Service
interface BookingService {
createBooking(bookingData: CreateBookingDTO): Promise<Booking>
updateBooking(bookingId: string, updates: UpdateBookingDTO): Promise<Booking>
cancelBooking(bookingId: string, reason: string): Promise<void>
getAvailability(practitionerId: string, date: Date): Promise<TimeSlot[]>
blockTimeSlot(practitionerId: string, timeSlot: TimeSlot): Promise<void>
startSession(bookingId: string): Promise<Session>
endSession(sessionId: string, notes: string): Promise<void>
}
Payment Service
interface PaymentService {
createPaymentIntent(amount: number, currency: string): Promise<PaymentIntent>
confirmPayment(paymentIntentId: string): Promise<PaymentResult>
refundPayment(paymentId: string, amount?: number): Promise<Refund>
createSubscription(planId: string, customerId: string): Promise<Subscription>
updateSubscription(subscriptionId: string, updates: SubscriptionUpdate): Promise<Subscription>
cancelSubscription(subscriptionId: string): Promise<void>
createPayout(practitionerId: string, amount: number): Promise<Payout>
getPayoutHistory(practitionerId: string): Promise<Payout[]>
}
3. Technology Stack
3.1 Frontend Technologies
| Component | Technology | Version | Purpose |
|---|
| Web Framework | Next.js | 14.x | React-based full-stack framework |
| Mobile Framework | React Native | 0.73.x | Cross-platform mobile development |
| UI Library | Tailwind CSS | 3.x | Utility-first CSS framework |
| Component Library | Headless UI | 1.x | Unstyled, accessible components |
| State Management | Zustand | 4.x | Lightweight state management |
| Form Handling | React Hook Form | 7.x | Performant forms with validation |
| HTTP Client | Axios | 1.x | Promise-based HTTP client |
| Real-time | Socket.io Client | 4.x | WebSocket communication |
3.2 Backend Technologies
| Component | Technology | Version | Purpose |
|---|
| Runtime | Node.js | 20.x LTS | JavaScript runtime |
| Framework | Express.js | 4.x | Web application framework |
| Language | TypeScript | 5.x | Type-safe JavaScript |
| API Documentation | Swagger/OpenAPI | 3.x | API documentation |
| Validation | Joi | 17.x | Data validation |
| ORM | Prisma | 5.x | Database ORM |
| Authentication | Passport.js | 0.7.x | Authentication middleware |
| File Upload | Multer | 1.x | File upload handling |
3.3 Database Technologies
| Component | Technology | Version | Purpose |
|---|
| Primary Database | PostgreSQL | 15.x | Relational data storage |
| Document Store | MongoDB | 7.x | Flexible document storage |
| Cache | Redis | 7.x | In-memory caching |
| Search Engine | Elasticsearch | 8.x | Full-text search |
| Time Series | InfluxDB | 2.x | Analytics and metrics |
| Message Queue | Apache Kafka | 3.x | Event streaming |
3.4 Infrastructure Technologies
| Component | Technology | Version | Purpose |
|---|
| Cloud Provider | AWS | Latest | Cloud infrastructure |
| Containerization | Docker | 24.x | Application containerization |
| Orchestration | Kubernetes | 1.28.x | Container orchestration |
| Service Mesh | Istio | 1.19.x | Service communication |
| Monitoring | DataDog | Latest | Application monitoring |
| Logging | ELK Stack | 8.x | Centralized logging |
| CI/CD | GitHub Actions | Latest | Continuous integration |
| CDN | CloudFlare | Latest | Content delivery |
4. Database Design
4.1 PostgreSQL Schema
Core Tables
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255),
first_name VARCHAR(100) NOT NULL,
last_name VARCHAR(100) NOT NULL,
phone VARCHAR(20),
date_of_birth DATE,
gender VARCHAR(20),
user_type VARCHAR(20) NOT NULL CHECK (user_type IN ('seeker', 'practitioner', 'admin')),
status VARCHAR(20) DEFAULT 'active' CHECK (status IN ('active', 'inactive', 'suspended')),
email_verified BOOLEAN DEFAULT FALSE,
phone_verified BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE TABLE practitioners (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
bio TEXT,
experience_years INTEGER,
hourly_rate DECIMAL(10,2),
languages TEXT[],
certifications JSONB,
specializations TEXT[],
availability JSONB,
verification_status VARCHAR(20) DEFAULT 'pending' CHECK (verification_status IN ('pending', 'verified', 'rejected')),
verification_documents JSONB,
rating DECIMAL(3,2) DEFAULT 0.00,
total_sessions INTEGER DEFAULT 0,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE TABLE services (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) NOT NULL,
description TEXT,
category_id UUID REFERENCES service_categories(id),
duration_minutes INTEGER NOT NULL,
base_price DECIMAL(10,2),
status VARCHAR(20) DEFAULT 'active' CHECK (status IN ('active', 'inactive')),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE TABLE bookings (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
seeker_id UUID REFERENCES users(id) ON DELETE CASCADE,
practitioner_id UUID REFERENCES practitioners(id) ON DELETE CASCADE,
service_id UUID REFERENCES services(id),
scheduled_at TIMESTAMP WITH TIME ZONE NOT NULL,
duration_minutes INTEGER NOT NULL,
total_amount DECIMAL(10,2) NOT NULL,
commission_amount DECIMAL(10,2) NOT NULL,
status VARCHAR(20) DEFAULT 'pending' CHECK (status IN ('pending', 'confirmed', 'completed', 'cancelled')),
cancellation_reason TEXT,
notes TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE TABLE payments (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
booking_id UUID REFERENCES bookings(id) ON DELETE CASCADE,
amount DECIMAL(10,2) NOT NULL,
currency VARCHAR(3) DEFAULT 'INR',
payment_method VARCHAR(50) NOT NULL,
payment_gateway VARCHAR(50) NOT NULL,
gateway_transaction_id VARCHAR(255),
status VARCHAR(20) DEFAULT 'pending' CHECK (status IN ('pending', 'completed', 'failed', 'refunded')),
processed_at TIMESTAMP WITH TIME ZONE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE TABLE reviews (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
booking_id UUID REFERENCES bookings(id) ON DELETE CASCADE,
reviewer_id UUID REFERENCES users(id) ON DELETE CASCADE,
reviewee_id UUID REFERENCES users(id) ON DELETE CASCADE,
rating INTEGER NOT NULL CHECK (rating >= 1 AND rating <= 5),
comment TEXT,
is_anonymous BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
Indexes for Performance
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_type_status ON users(user_type, status);
CREATE INDEX idx_practitioners_user_id ON practitioners(user_id);
CREATE INDEX idx_practitioners_verification ON practitioners(verification_status);
CREATE INDEX idx_bookings_seeker ON bookings(seeker_id);
CREATE INDEX idx_bookings_practitioner ON bookings(practitioner_id);
CREATE INDEX idx_bookings_scheduled ON bookings(scheduled_at);
CREATE INDEX idx_bookings_status ON bookings(status);
CREATE INDEX idx_payments_booking ON payments(booking_id);
CREATE INDEX idx_payments_status ON payments(status);
CREATE INDEX idx_reviews_booking ON reviews(booking_id);
CREATE INDEX idx_reviews_reviewee ON reviews(reviewee_id);
CREATE INDEX idx_bookings_practitioner_date ON bookings(practitioner_id, scheduled_at);
CREATE INDEX idx_practitioners_rating_sessions ON practitioners(rating DESC, total_sessions DESC);
4.2 MongoDB Collections
Content Management
{
_id: ObjectId,
title: String,
slug: String,
content: String,
excerpt: String,
author: {
id: String,
name: String,
avatar: String
},
category: String,
tags: [String],
featured_image: String,
seo: {
title: String,
description: String,
keywords: [String]
},
status: String,
published_at: Date,
created_at: Date,
updated_at: Date
}
{
_id: ObjectId,
conversation_id: String,
sender_id: String,
recipient_id: String,
message_type: String,
content: String,
attachments: [{
type: String,
url: String,
filename: String,
size: Number
}],
read_at: Date,
created_at: Date
}
4.3 Redis Cache Structure
"session:{sessionId}" => {
userId: String,
userType: String,
permissions: [String],
expiresAt: Number
}
"availability:{practitionerId}:{date}" => {
timeSlots: [{
start: String,
end: String,
available: Boolean
}],
lastUpdated: Number
}
"search:{query}:{filters}:{page}" => {
results: [Object],
totalCount: Number,
facets: Object,
cachedAt: Number
}
"rate_limit:{userId}:{endpoint}" => {
count: Number,
resetTime: Number
}
5. API Architecture
5.1 RESTful API Design
API Versioning Strategy
Base URL: https://api.klearkarma.com/v1/
Versioning approaches:
1. URL versioning: /v1/, /v2/
2. Header versioning: Accept: application/vnd.klearkarma.v1+json
3. Query parameter: ?version=1
Standard Response Format
interface APIResponse<T> {
success: boolean;
data?: T;
error?: {
code: string;
message: string;
details?: any;
};
meta?: {
pagination?: {
page: number;
limit: number;
total: number;
totalPages: number;
};
timestamp: string;
requestId: string;
};
}
Core API Endpoints
POST /auth/register
POST /auth/login
POST /auth/refresh
POST /auth/logout
POST /auth/forgot-password
POST /auth/reset-password
GET /users/profile
PUT /users/profile
POST /users/upload-avatar
DELETE /users/account
GET /practitioners
GET /practitioners/{id}
POST /practitioners
PUT /practitioners/{id}
GET /practitioners/{id}/availability
PUT /practitioners/{id}/availability
GET /practitioners/{id}/reviews
POST /bookings
GET /bookings
GET /bookings/{id}
PUT /bookings/{id}
DELETE /bookings/{id}
POST /bookings/{id}/cancel
POST /payments/create-intent
POST /payments/confirm
POST /payments/refund
GET /payments/history
GET /search/practitioners
GET /search/services
GET /search/suggestions
5.2 GraphQL API
Schema Definition
type User {
id: ID!
email: String!
firstName: String!
lastName: String!
userType: UserType!
profile: Profile
createdAt: DateTime!
}
type Practitioner {
id: ID!
user: User!
bio: String
experienceYears: Int
hourlyRate: Float
specializations: [String!]!
rating: Float
totalSessions: Int
availability: [TimeSlot!]!
services: [Service!]!
reviews: [Review!]!
}
type Booking {
id: ID!
seeker: User!
practitioner: Practitioner!
service: Service!
scheduledAt: DateTime!
duration: Int!
totalAmount: Float!
status: BookingStatus!
payment: Payment
}
type Query {
me: User
practitioner(id: ID!): Practitioner
practitioners(filters: PractitionerFilters, pagination: Pagination): PractitionerConnection!
booking(id: ID!): Booking
myBookings(status: BookingStatus, pagination: Pagination): BookingConnection!
}
type Mutation {
updateProfile(input: UpdateProfileInput!): User!
createBooking(input: CreateBookingInput!): Booking!
cancelBooking(id: ID!, reason: String): Booking!
createReview(input: CreateReviewInput!): Review!
}
type Subscription {
bookingUpdated(bookingId: ID!): Booking!
newMessage(conversationId: ID!): Message!
}
5.3 WebSocket Events
interface WebSocketEvents {
'booking:created': (booking: Booking) => void;
'booking:updated': (booking: Booking) => void;
'booking:cancelled': (bookingId: string, reason: string) => void;
'message:new': (message: Message) => void;
'message:read': (messageId: string) => void;
'typing:start': (userId: string) => void;
'typing:stop': (userId: string) => void;
'notification:new': (notification: Notification) => void;
'notification:read': (notificationId: string) => void;
'user:online': (userId: string) => void;
'user:offline': (userId: string) => void;
}
6. Security Framework
6.1 Authentication & Authorization
JWT Token Structure
interface JWTPayload {
sub: string;
email: string;
userType: 'seeker' | 'practitioner' | 'admin';
permissions: string[];
iat: number;
exp: number;
jti: string;
}
Role-Based Access Control (RBAC)
interface Permission {
resource: string;
action: string;
conditions?: Record<string, any>;
}
interface Role {
name: string;
permissions: Permission[];
}
const roles: Record<string, Role> = {
seeker: {
name: 'seeker',
permissions: [
{ resource: 'booking', action: 'create' },
{ resource: 'booking', action: 'read', conditions: { owner: true } },
{ resource: 'review', action: 'create' },
{ resource: 'profile', action: 'update', conditions: { owner: true } }
]
},
practitioner: {
name: 'practitioner',
permissions: [
{ resource: 'booking', action: 'read', conditions: { practitioner: true } },
{ resource: 'booking', action: 'update', conditions: { practitioner: true } },
{ resource: 'availability', action: 'update', conditions: { owner: true } },
{ resource: 'profile', action: 'update', conditions: { owner: true } }
]
}
};
6.2 Data Protection
Encryption Standards
- Data at Rest: AES-256 encryption
- Data in Transit: TLS 1.3
- Password Hashing: bcrypt with salt rounds 12
- Sensitive Data: Field-level encryption for PII
Data Privacy Compliance
interface DataSubject {
userId: string;
email: string;
consentGiven: boolean;
consentDate: Date;
dataRetentionPeriod: number;
}
class GDPRCompliance {
async exportUserData(userId: string): Promise<UserDataExport> {
}
async deleteUserData(userId: string): Promise<void> {
}
async updateConsent(userId: string, consent: ConsentUpdate): Promise<void> {
}
}
6.3 Security Monitoring
Security Event Logging
interface SecurityEvent {
eventType: 'login' | 'logout' | 'failed_login' | 'permission_denied' | 'data_access';
userId?: string;
ipAddress: string;
userAgent: string;
timestamp: Date;
metadata: Record<string, any>;
riskScore: number;
}
class SecurityMonitor {
async logSecurityEvent(event: SecurityEvent): Promise<void> {
await this.analyzeRisk(event);
if (event.riskScore > 0.8) {
await this.triggerAlert(event);
}
}
private async analyzeRisk(event: SecurityEvent): Promise<number> {
return this.riskAnalysisModel.predict(event);
}
}
7. Scalability & Performance
7.1 Horizontal Scaling Strategy
Microservices Scaling
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
spec:
replicas: 3
selector:
matchLabels:
app: user-service
template:
metadata:
labels:
app: user-service
spec:
containers:
- name: user-service
image: klearkarma/user-service:latest
ports:
- containerPort: 3000
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: db-secret
key: url
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
---
apiVersion: v1
kind: Service
metadata:
name: user-service
spec:
selector:
app: user-service
ports:
- port: 80
targetPort: 3000
type: ClusterIP
Auto-scaling Configuration
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: user-service-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: user-service
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
7.2 Caching Strategy
Multi-Level Caching
class CacheManager {
private l1Cache: Map<string, any> = new Map();
private l2Cache: Redis;
private l3Cache: CDN;
async get<T>(key: string): Promise<T | null> {
if (this.l1Cache.has(key)) {
return this.l1Cache.get(key);
}
const l2Value = await this.l2Cache.get(key);
if (l2Value) {
this.l1Cache.set(key, l2Value);
return l2Value;
}
return null;
}
async set<T>(key: string, value: T, ttl: number): Promise<void> {
this.l1Cache.set(key, value);
await this.l2Cache.setex(key, ttl, JSON.stringify(value));
}
}
Cache Invalidation Strategy
class CacheInvalidation {
async invalidateUserCache(userId: string): Promise<void> {
const patterns = [
`user:${userId}:*`,
`profile:${userId}`,
`bookings:${userId}:*`,
`availability:${userId}:*`
];
await Promise.all(
patterns.map(pattern => this.redis.del(pattern))
);
}
async invalidateSearchCache(filters: SearchFilters): Promise<void> {
const cacheKey = this.generateSearchCacheKey(filters);
await this.redis.del(cacheKey);
}
}
7.3 Database Optimization
Read Replicas Configuration
class DatabaseManager {
private writeDB: Pool;
private readDBs: Pool[];
private currentReadIndex = 0;
async executeQuery(query: string, params: any[], readOnly = false): Promise<any> {
if (readOnly) {
return this.executeReadQuery(query, params);
} else {
return this.executeWriteQuery(query, params);
}
}
private async executeReadQuery(query: string, params: any[]): Promise<any> {
const readDB = this.getNextReadDB();
return readDB.query(query, params);
}
private getNextReadDB(): Pool {
const db = this.readDBs[this.currentReadIndex];
this.currentReadIndex = (this.currentReadIndex + 1) % this.readDBs.length;
return db;
}
}
Query Optimization
EXPLAIN ANALYZE
SELECT
p.id,
u.first_name,
u.last_name,
p.bio,
p.hourly_rate,
p.rating,
p.total_sessions,
array_agg(DISTINCT s.name) as services
FROM practitioners p
JOIN users u ON p.user_id = u.id
JOIN practitioner_services ps ON p.id = ps.practitioner_id
JOIN services s ON ps.service_id = s.id
WHERE
p.verification_status = 'verified'
AND u.status = 'active'
AND p.specializations && $1
AND p.hourly_rate BETWEEN $2 AND $3
AND ST_DWithin(p.location, ST_Point($4, $5), $6)
GROUP BY p.id, u.first_name, u.last_name, p.bio, p.hourly_rate, p.rating, p.total_sessions
ORDER BY
p.rating DESC,
p.total_sessions DESC,
ST_Distance(p.location, ST_Point($4, $5)) ASC
LIMIT $7 OFFSET $8;
8. DevOps & Infrastructure
8.1 CI/CD Pipeline
GitHub Actions Workflow
name: CI/CD Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm run test:coverage
- name: Upload coverage
uses: codecov/codecov-action@v3
build:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build Docker image
run: |
docker build -t ${{ secrets.ECR_REGISTRY }}/klearkarma-api:${{ github.sha }} .
docker tag ${{ secrets.ECR_REGISTRY }}/klearkarma-api:${{ github.sha }} ${{ secrets.ECR_REGISTRY }}/klearkarma-api:latest
- name: Push to ECR
run: |
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin ${{ secrets.ECR_REGISTRY }}
docker push ${{ secrets.ECR_REGISTRY }}/klearkarma-api:${{ github.sha }}
docker push ${{ secrets.ECR_REGISTRY }}/klearkarma-api:latest
deploy:
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- name: Deploy to EKS
run: |
aws eks update-kubeconfig --region us-east-1 --name klearkarma-cluster
kubectl set image deployment/api-deployment api=${{ secrets.ECR_REGISTRY }}/klearkarma-api:${{ github.sha }}
kubectl rollout status deployment/api-deployment
8.2 Infrastructure as Code
Terraform Configuration
# main.tf
provider "aws" {
region = var.aws_region
}
# EKS Cluster
module "eks" {
source = "terraform-aws-modules/eks/aws"
cluster_name = "klearkarma-cluster"
cluster_version = "1.28"
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnets
node_groups = {
main = {
desired_capacity = 3
max_capacity = 10
min_capacity = 2
instance_types = ["t3.medium"]
k8s_labels = {
Environment = var.environment
Application = "klearkarma"
}
}
}
}
# RDS PostgreSQL
resource "aws_db_instance" "main" {
identifier = "klearkarma-db"
engine = "postgres"
engine_version = "15.4"
instance_class = "db.t3.micro"
allocated_storage = 20
max_allocated_storage = 100
storage_encrypted = true
db_name = "klearkarma"
username = var.db_username
password = var.db_password
vpc_security_group_ids = [aws_security_group.rds.id]
db_subnet_group_name = aws_db_subnet_group.main.name
backup_retention_period = 7
backup_window = "03:00-04:00"
maintenance_window = "sun:04:00-sun:05:00"
skip_final_snapshot = false
final_snapshot_identifier = "klearkarma-db-final-snapshot"
tags = {
Name = "klearkarma-db"
Environment = var.environment
}
}
# ElastiCache Redis
resource "aws_elasticache_subnet_group" "main" {
name = "klearkarma-cache-subnet"
subnet_ids = module.vpc.private_subnets
}
resource "aws_elasticache_replication_group" "main" {
replication_group_id = "klearkarma-redis"
description = "Redis cluster for Klear Karma"
node_type = "cache.t3.micro"
port = 6379
parameter_group_name = "default.redis7"
num_cache_clusters = 2
automatic_failover_enabled = true
multi_az_enabled = true
subnet_group_name = aws_elasticache_subnet_group.main.name
security_group_ids = [aws_security_group.redis.id]
at_rest_encryption_enabled = true
transit_encryption_enabled = true
tags = {
Name = "klearkarma-redis"
Environment = var.environment
}
}
8.3 Monitoring & Observability
DataDog Configuration
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: datadog-agent
spec:
selector:
matchLabels:
app: datadog-agent
template:
metadata:
labels:
app: datadog-agent
spec:
containers:
- name: datadog-agent
image: datadog/agent:latest
env:
- name: DD_API_KEY
valueFrom:
secretKeyRef:
name: datadog-secret
key: api-key
- name: DD_SITE
value: "datadoghq.com"
- name: DD_LOGS_ENABLED
value: "true"
- name: DD_APM_ENABLED
value: "true"
- name: DD_PROCESS_AGENT_ENABLED
value: "true"
volumeMounts:
- name: dockersocket
mountPath: /var/run/docker.sock
- name: procdir
mountPath: /host/proc
- name: cgroups
mountPath: /host/sys/fs/cgroup
volumes:
- name: dockersocket
hostPath:
path: /var/run/docker.sock
- name: procdir
hostPath:
path: /proc
- name: cgroups
hostPath:
path: /sys/fs/cgroup
Custom Metrics
class MetricsCollector {
private statsd: StatsD;
constructor() {
this.statsd = new StatsD({
host: process.env.DATADOG_HOST,
port: 8125,
prefix: 'klearkarma.'
});
}
recordBookingCreated(practitionerId: string, amount: number): void {
this.statsd.increment('bookings.created', 1, {
practitioner_id: practitionerId
});
this.statsd.histogram('bookings.amount', amount);
}
recordAPILatency(endpoint: string, duration: number): void {
this.statsd.histogram('api.latency', duration, {
endpoint: endpoint
});
}
recordUserAction(action: string, userId: string): void {
this.statsd.increment('user.actions', 1, {
action: action,
user_id: userId
});
}
}
9. AI/ML Integration
9.1 Recommendation Engine
Collaborative Filtering
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
from scipy.sparse import csr_matrix
class PractitionerRecommendationEngine:
def __init__(self):
self.user_item_matrix = None
self.item_similarity_matrix = None
def fit(self, interactions_df):
"""Train the recommendation model"""
self.user_item_matrix = self._create_interaction_matrix(interactions_df)
self.item_similarity_matrix = cosine_similarity(self.user_item_matrix.T)
def recommend_practitioners(self, user_id: str, n_recommendations: int = 5):
"""Get practitioner recommendations for a user"""
user_index = self._get_user_index(user_id)
user_ratings = self.user_item_matrix[user_index].toarray().flatten()
scores = np.zeros(self.user_item_matrix.shape[1])
for item_idx in range(len(user_ratings)):
if user_ratings[item_idx] > 0:
scores += (self.item_similarity_matrix[item_idx] * user_ratings[item_idx])
scores[user_ratings > 0] = 0
top_indices = np.argsort(scores)[::-1][:n_recommendations]
return [
{
'practitioner_id': self._get_practitioner_id(idx),
'score': scores[idx],
'reason': self._get_recommendation_reason(user_id, idx)
}
for idx in top_indices
]
Content-Based Filtering
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import linear_kernel
class ContentBasedRecommender:
def __init__(self):
self.tfidf_vectorizer = TfidfVectorizer(
max_features=5000,
stop_words='english',
ngram_range=(1, 2)
)
self.content_matrix = None
def fit(self, practitioners_df):
"""Train content-based model"""
content_features = practitioners_df.apply(
lambda x: f"{x['specializations']} {x['bio']} {x['certifications']}",
axis=1
)
self.content_matrix = self.tfidf_vectorizer.fit_transform(content_features)
def find_similar_practitioners(self, practitioner_id: str, n_similar: int = 5):
"""Find practitioners similar to the given one"""
practitioner_index = self._get_practitioner_index(practitioner_id)
similarity_scores = linear_kernel(
self.content_matrix[practitioner_index],
self.content_matrix
).flatten()
similar_indices = np.argsort(similarity_scores)[::-1][1:n_similar+1]
return [
{
'practitioner_id': self._get_practitioner_id(idx),
'similarity_score': similarity_scores[idx]
}
for idx in similar_indices
]
9.2 Fraud Detection
Anomaly Detection Model
from sklearn.ensemble import IsolationForest
from sklearn.preprocessing import StandardScaler
import pandas as pd
class FraudDetectionModel:
def __init__(self):
self.isolation_forest = IsolationForest(
contamination=0.1,
random_state=42
)
self.scaler = StandardScaler()
self.feature_columns = [
'booking_amount',
'time_since_registration',
'previous_bookings_count',
'avg_session_duration',
'cancellation_rate',
'payment_method_changes',
'login_frequency',
'device_changes'
]
def extract_features(self, user_data: dict) -> np.ndarray:
"""Extract features for fraud detection"""
features = []
features.append(user_data.get('booking_amount', 0))
features.append(user_data.get('time_since_registration', 0))
features.append(user_data.get('previous_bookings_count', 0))
features.append(user_data.get('avg_session_duration', 0))
features.append(user_data.get('cancellation_rate', 0))
features.append(user_data.get('payment_method_changes', 0))
features.append(user_data.get('login_frequency', 0))
features.append(user_data.get('device_changes', 0))
return np.array(features).reshape(1, -1)
def predict_fraud_probability(self, user_data: dict) -> float:
"""Predict fraud probability for a user"""
features = self.extract_features(user_data)
scaled_features = self.scaler.transform(features)
anomaly_score = self.isolation_forest.decision_function(scaled_features)[0]
fraud_probability = max(0, (1 - anomaly_score) / 2)
return fraud_probability
def train(self, training_data: pd.DataFrame):
"""Train the fraud detection model"""
features = training_data[self.feature_columns]
scaled_features = self.scaler.fit_transform(features)
self.isolation_forest.fit(scaled_features)
9.3 Natural Language Processing
Review Sentiment Analysis
from transformers import pipeline, AutoTokenizer, AutoModelForSequenceClassification
import torch
class ReviewSentimentAnalyzer:
def __init__(self):
self.model_name = "cardiffnlp/twitter-roberta-base-sentiment-latest"
self.tokenizer = AutoTokenizer.from_pretrained(self.model_name)
self.model = AutoModelForSequenceClassification.from_pretrained(self.model_name)
self.sentiment_pipeline = pipeline(
"sentiment-analysis",
model=self.model,
tokenizer=self.tokenizer,
device=0 if torch.cuda.is_available() else -1
)
def analyze_review(self, review_text: str) -> dict:
"""Analyze sentiment of a review"""
cleaned_text = self._preprocess_text(review_text)
result = self.sentiment_pipeline(cleaned_text)[0]
aspects = self._extract_aspects(cleaned_text)
return {
'sentiment': result['label'],
'confidence': result['score'],
'aspects': aspects,
'summary': self._generate_summary(cleaned_text, result)
}
def _extract_aspects(self, text: str) -> list:
"""Extract aspects mentioned in the review"""
aspect_keywords = {
'communication': ['communication', 'responsive', 'reply', 'contact'],
'expertise': ['knowledgeable', 'expert', 'skilled', 'experienced'],
'punctuality': ['on time', 'punctual', 'late', 'early'],
'effectiveness': ['helpful', 'effective', 'results', 'improvement'],
'professionalism': ['professional', 'courteous', 'respectful']
}
detected_aspects = []
text_lower = text.lower()
for aspect, keywords in aspect_keywords.items():
if any(keyword in text_lower for keyword in keywords):
detected_aspects.append(aspect)
return detected_aspects
10. Mobile Architecture
10.1 React Native Structure
App Architecture
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';
import { store, persistor } from './src/store';
import { AuthNavigator } from './src/navigation/AuthNavigator';
import { AppNavigator } from './src/navigation/AppNavigator';
import { useAuthState } from './src/hooks/useAuthState';
const App: React.FC = () => {
return (
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<NavigationContainer>
<AppContent />
</NavigationContainer>
</PersistGate>
</Provider>
);
};
const AppContent: React.FC = () => {
const { isAuthenticated, isLoading } = useAuthState();
if (isLoading) {
return <LoadingScreen />;
}
return isAuthenticated ? <AppNavigator /> : <AuthNavigator />;
};
Navigation Structure
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { createStackNavigator } from '@react-navigation/stack';
const Tab = createBottomTabNavigator();
const Stack = createStackNavigator();
const TabNavigator: React.FC = () => {
return (
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
return <TabIcon route={route.name} focused={focused} color={color} size={size} />;
},
tabBarActiveTintColor: '#6366f1',
tabBarInactiveTintColor: 'gray',
})}
>
<Tab.Screen name="Home" component={HomeStack} />
<Tab.Screen name="Search" component={SearchStack} />
<Tab.Screen name="Bookings" component={BookingsStack} />
<Tab.Screen name="Messages" component={MessagesStack} />
<Tab.Screen name="Profile" component={ProfileStack} />
</Tab.Navigator>
);
};
const HomeStack: React.FC = () => {
return (
<Stack.Navigator>
<Stack.Screen name="HomeScreen" component={HomeScreen} />
<Stack.Screen name="PractitionerDetail" component={PractitionerDetailScreen} />
<Stack.Screen name="BookingFlow" component={BookingFlowScreen} />
</Stack.Navigator>
);
};
10.2 State Management
Redux Store Configuration
import { configureStore } from '@reduxjs/toolkit';
import { persistStore, persistReducer } from 'redux-persist';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { authSlice } from './slices/authSlice';
import { userSlice } from './slices/userSlice';
import { bookingSlice } from './slices/bookingSlice';
import { apiSlice } from './api/apiSlice';
const persistConfig = {
key: 'root',
storage: AsyncStorage,
whitelist: ['auth', 'user'],
};
const rootReducer = {
auth: persistReducer(persistConfig, authSlice.reducer),
user: userSlice.reducer,
booking: bookingSlice.reducer,
api: apiSlice.reducer,
};
export const store = configureStore({
reducer: rootReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: ['persist/PERSIST', 'persist/REHYDRATE'],
},
}).concat(apiSlice.middleware),
});
export const persistor = persistStore(store);
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
API Slice with RTK Query
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
import { RootState } from '../index';
export const apiSlice = createApi({
reducerPath: 'api',
baseQuery: fetchBaseQuery({
baseUrl: process.env.REACT_APP_API_URL,
prepareHeaders: (headers, { getState }) => {
const token = (getState() as RootState).auth.token;
if (token) {
headers.set('authorization', `Bearer ${token}`);
}
return headers;
},
}),
tagTypes: ['User', 'Practitioner', 'Booking', 'Review'],
endpoints: (builder) => ({
getProfile: builder.query<User, void>({
query: () => '/users/profile',
providesTags: ['User'],
}),
updateProfile: builder.mutation<User, Partial<User>>({
query: (updates) => ({
url: '/users/profile',
method: 'PUT',
body: updates,
}),
invalidatesTags: ['User'],
}),
searchPractitioners: builder.query<PractitionerSearchResult, SearchFilters>({
query: (filters) => ({
url: '/search/practitioners',
params: filters,
}),
providesTags: ['Practitioner'],
}),
createBooking: builder.mutation<Booking, CreateBookingRequest>({
query: (bookingData) => ({
url: '/bookings',
method: 'POST',
body: bookingData,
}),
invalidatesTags: ['Booking'],
}),
getBookings: builder.query<Booking[], BookingFilters>({
query: (filters) => ({
url: '/bookings',
params: filters,
}),
providesTags: ['Booking'],
}),
}),
});
export const {
useGetProfileQuery,
useUpdateProfileMutation,
useSearchPractitionersQuery,
useCreateBookingMutation,
useGetBookingsQuery,
} = apiSlice;
10.3 Platform-Specific Features
iOS Integration
import HealthKit
class HealthKitManager {
private let healthStore = HKHealthStore()
func requestAuthorization() {
let readTypes: Set<HKObjectType> = [
HKObjectType.quantityType(forIdentifier: .heartRate)!,
HKObjectType.quantityType(forIdentifier: .stepCount)!,
HKObjectType.categoryType(forIdentifier: .sleepAnalysis)!
]
healthStore.requestAuthorization(toShare: nil, read: readTypes) { success, error in
if success {
self.startHealthDataCollection()
}
}
}
func getHeartRateData(completion: @escaping ([HKQuantitySample]) -> Void) {
let heartRateType = HKQuantityType.quantityType(forIdentifier: .heartRate)!
let query = HKSampleQuery(sampleType: heartRateType, predicate: nil, limit: 10, sortDescriptors: nil) { _, samples, _ in
completion(samples as? [HKQuantitySample] ?? [])
}
healthStore.execute(query)
}
}
Android Integration
class GoogleFitManager(private val context: Context) {
private val fitnessOptions = FitnessOptions.builder()
.addDataType(DataType.TYPE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
.addDataType(DataType.TYPE_HEART_RATE_BPM, FitnessOptions.ACCESS_READ)
.build()
fun requestPermissions(activity: Activity) {
if (!GoogleSignIn.hasPermissions(GoogleSignIn.getLastSignedInAccount(context), fitnessOptions)) {
GoogleSignIn.requestPermissions(
activity,
GOOGLE_FIT_PERMISSIONS_REQUEST_CODE,
GoogleSignIn.getLastSignedInAccount(context),
fitnessOptions
)
}
}
fun readStepCount(callback: (Int) -> Unit) {
val account = GoogleSignIn.getLastSignedInAccount(context)
if (account != null) {
Fitness.getHistoryClient(context, account)
.readDailyTotal(DataType.TYPE_STEP_COUNT_DELTA)
.addOnSuccessListener { result ->
val totalSteps = result.dataPoints.firstOrNull()?.getValue(Field.FIELD_STEPS)?.asInt() ?: 0
callback(totalSteps)
}
}
}
}
10.4 Offline Capabilities
Data Synchronization
class OfflineManager {
private db: SQLiteDatabase;
private syncQueue: SyncOperation[] = [];
async initializeOfflineStorage(): Promise<void> {
this.db = await SQLite.openDatabase({
name: 'klearkarma_offline.db',
location: 'default',
});
await this.createTables();
}
async cacheUserData(userData: User): Promise<void> {
await this.db.executeSql(
'INSERT OR REPLACE INTO cached_users (id, data, cached_at) VALUES (?, ?, ?)',
[userData.id, JSON.stringify(userData), Date.now()]
);
}
async getCachedBookings(): Promise<Booking[]> {
const [results] = await this.db.executeSql(
'SELECT data FROM cached_bookings WHERE user_id = ? ORDER BY created_at DESC',
[this.getCurrentUserId()]
);
return results.rows.raw().map(row => JSON.parse(row.data));
}
async queueSyncOperation(operation: SyncOperation): Promise<void> {
this.syncQueue.push(operation);
await this.persistSyncQueue();
if (await this.isOnline()) {
await this.processSyncQueue();
}
}
async processSyncQueue(): Promise<void> {
while (this.syncQueue.length > 0) {
const operation = this.syncQueue.shift()!;
try {
await this.executeSync(operation);
await this.markSyncComplete(operation.id);
} catch (error) {
console.error('Sync failed:', error);
this.syncQueue.unshift(operation);
break;
}
}
}
}
Performance Optimization
Code Splitting & Lazy Loading
const PractitionerDetail = lazy(() => import('../screens/PractitionerDetail'));
const BookingFlow = lazy(() => import('../screens/BookingFlow'));
const PaymentScreen = lazy(() => import('../screens/PaymentScreen'));
const LazyScreen: React.FC<{component: React.ComponentType}> = ({ component: Component }) => {
return (
<Suspense fallback={<LoadingSpinner />}>
<Component />
</Suspense>
);
};
Image Optimization
const OptimizedImage: React.FC<ImageProps> = ({ source, style, ...props }) => {
const [loading, setLoading] = useState(true);
const [error, setError] = useState(false);
return (
<View style={style}>
{loading && <ImagePlaceholder />}
<Image
source={source}
style={[style, { opacity: loading ? 0 : 1 }]}
onLoad={() => setLoading(false)}
onError={() => {
setLoading(false);
setError(true);
}}
resizeMode="cover"
{...props}
/>
{error && <ImageErrorPlaceholder />}
</View>
);
};
Security Implementation
Biometric Authentication
import TouchID from 'react-native-touch-id';
class BiometricAuth {
static async isSupported(): Promise<boolean> {
try {
const biometryType = await TouchID.isSupported();
return biometryType !== false;
} catch {
return false;
}
}
static async authenticate(reason: string): Promise<boolean> {
try {
await TouchID.authenticate(reason, {
title: 'Authenticate',
subtitle: 'Use your biometric to access Klear Karma',
description: reason,
fallbackLabel: 'Use Passcode',
cancelLabel: 'Cancel',
});
return true;
} catch (error) {
console.error('Biometric authentication failed:', error);
return false;
}
}
}
Secure Storage
import { setInternetCredentials, getInternetCredentials, resetInternetCredentials } from 'react-native-keychain';
class SecureStorage {
private static readonly SERVICE_NAME = 'KlearKarmaApp';
static async storeToken(token: string): Promise<void> {
await setInternetCredentials(
this.SERVICE_NAME,
'auth_token',
token
);
}
static async getToken(): Promise<string | null> {
try {
const credentials = await getInternetCredentials(this.SERVICE_NAME);
return credentials ? credentials.password : null;
} catch {
return null;
}
}
static async clearToken(): Promise<void> {
await resetInternetCredentials(this.SERVICE_NAME);
}
}
Testing Strategy
Unit Testing
module.exports = {
preset: 'react-native',
setupFilesAfterEnv: ['<rootDir>/src/test/setup.ts'],
testMatch: ['**/__tests__/**/*.test.{js,ts,tsx}'],
collectCoverageFrom: [
'src/**/*.{js,ts,tsx}',
'!src/**/*.d.ts',
'!src/test/**',
],
coverageThreshold: {
global: {
branches: 80,
functions: 80,
lines: 80,
statements: 80,
},
},
};
import { render, fireEvent, waitFor } from '@testing-library/react-native';
import { LoginScreen } from '../LoginScreen';
describe('LoginScreen', () => {
it('should handle login form submission', async () => {
const mockLogin = jest.fn();
const { getByTestId } = render(<LoginScreen onLogin={mockLogin} />);
fireEvent.changeText(getByTestId('email-input'), 'test@example.com');
fireEvent.changeText(getByTestId('password-input'), 'password123');
fireEvent.press(getByTestId('login-button'));
await waitFor(() => {
expect(mockLogin).toHaveBeenCalledWith({
email: 'test@example.com',
password: 'password123',
});
});
});
});
Integration Testing
describe('Klear Karma App', () => {
beforeAll(async () => {
await device.launchApp();
});
beforeEach(async () => {
await device.reloadReactNative();
});
it('should complete booking flow', async () => {
await element(by.id('email-input')).typeText('test@example.com');
await element(by.id('password-input')).typeText('password123');
await element(by.id('login-button')).tap();
await element(by.id('search-tab')).tap();
await element(by.id('search-input')).typeText('yoga');
await element(by.id('search-button')).tap();
await element(by.id('practitioner-card-0')).tap();
await element(by.id('book-session-button')).tap();
await element(by.id('time-slot-0')).tap();
await element(by.id('confirm-booking-button')).tap();
await expect(element(by.text('Booking Confirmed'))).toBeVisible();
});
});
This comprehensive technical architecture document provides the foundation for building a scalable, secure, and maintainable platform that can support Klear Karma's growth from startup to market leader in the alternative healing space.