Skip to content
Platform Docs

Equipment Care

Proper maintenance of your subscription management infrastructure and development tools is essential for optimal performance and reliability. This guide covers best practices for maintaining your ToroSachi integration and related systems.

Ensure your infrastructure meets these minimum requirements:

  • CPU: 2+ cores for production environments
  • RAM: 4GB minimum, 8GB recommended
  • Storage: SSD recommended for database operations
  • Network: Reliable internet connection for administration and order workflows
  • SSL: Valid SSL certificate for all endpoints

Daily Checks:

  • API response times < 500ms
  • Webhook delivery success rate > 99%
  • Database connection pool health
  • SSL certificate validity
  • Log file sizes and rotation

Weekly Maintenance:

  • Security updates installation
  • Database optimization and cleanup
  • Log analysis and archival
  • Performance metrics review
  • Backup verification

Monthly Reviews:

  • Capacity planning assessment
  • Security audit and vulnerability scanning
  • Disaster recovery testing
  • Performance trend analysis
  • Cost optimization review

For PostgreSQL databases storing subscription data:

-- Weekly maintenance queries
VACUUM ANALYZE subscriptions;
VACUUM ANALYZE payments;
VACUUM ANALYZE customers;
-- Monthly index maintenance
REINDEX INDEX idx_subscriptions_status;
REINDEX INDEX idx_payments_created_at;
-- Check database size
SELECT
schemaname,
tablename,
pg_size_pretty(pg_total_relation_size(tablename::text)) as size
FROM pg_tables
WHERE schemaname = 'public'
ORDER BY pg_total_relation_size(tablename::text) DESC;

For MySQL databases:

-- Optimize tables weekly
OPTIMIZE TABLE subscriptions;
OPTIMIZE TABLE payments;
OPTIMIZE TABLE customers;
-- Check table health
CHECK TABLE subscriptions;
CHECK TABLE payments;
-- Analyze query performance
SHOW PROCESSLIST;
EXPLAIN SELECT * FROM subscriptions WHERE status = 'active';

Automated Backup Script:

#!/bin/bash
# Daily backup script
DB_NAME="torosachi_prod"
BACKUP_DIR="/backups/database"
DATE=$(date +%Y%m%d_%H%M%S)
# Create backup
pg_dump $DB_NAME > "$BACKUP_DIR/backup_$DATE.sql"
# Compress backup
gzip "$BACKUP_DIR/backup_$DATE.sql"
# Remove backups older than 30 days
find $BACKUP_DIR -name "backup_*.sql.gz" -mtime +30 -delete
# Verify backup integrity
gunzip -t "$BACKUP_DIR/backup_$DATE.sql.gz"
if [ $? -eq 0 ]; then
echo "Backup successful: backup_$DATE.sql.gz"
else
echo "Backup verification failed!"
exit 1
fi

Package Management:

Terminal window
# Regular dependency updates
npm audit --fix
npm update
# Check for outdated packages
npm outdated
# Clean package cache
npm cache clean --force
# Verify installation integrity
npm doctor

Memory Management:

// Monitor memory usage
const used = process.memoryUsage();
console.log({
rss: Math.round((used.rss / 1024 / 1024) * 100) / 100 + " MB",
heapTotal: Math.round((used.heapTotal / 1024 / 1024) * 100) / 100 + " MB",
heapUsed: Math.round((used.heapUsed / 1024 / 1024) * 100) / 100 + " MB",
});
// Implement graceful shutdown
process.on("SIGTERM", () => {
console.log("SIGTERM received, shutting down gracefully");
server.close(() => {
console.log("Process terminated");
});
});
  • Implement exponential backoff for retries
  • Cache frequently accessed data
  • Use bulk operations when available
  • Monitor rate limit headers
// Rate limit aware HTTP client
class ToroSachiClient {
constructor(apiKey) {
this.apiKey = apiKey;
this.rateLimitRemaining = 1000;
this.rateLimitReset = Date.now();
}
async makeRequest(endpoint, options = {}) {
// Check rate limit
if (this.rateLimitRemaining <= 10 && Date.now() < this.rateLimitReset) {
const waitTime = this.rateLimitReset - Date.now();
await new Promise((resolve) => setTimeout(resolve, waitTime));
}
const response = await fetch(`https://api.torosachi.com/v1${endpoint}`, {
...options,
headers: {
Authorization: `Bearer ${this.apiKey}`,
"Content-Type": "application/json",
...options.headers,
},
});
// Update rate limit info
this.rateLimitRemaining = parseInt(
response.headers.get("X-RateLimit-Remaining"),
);
this.rateLimitReset =
parseInt(response.headers.get("X-RateLimit-Reset")) * 1000;
return response;
}
}
// Webhook endpoint health check
app.get("/webhooks/health", (req, res) => {
const health = {
status: "healthy",
timestamp: new Date().toISOString(),
uptime: process.uptime(),
memory: process.memoryUsage(),
version: process.env.npm_package_version,
};
res.status(200).json(health);
});
// Webhook processing with error handling
app.post("/webhooks/torosachi", async (req, res) => {
try {
const signature = req.headers["x-torosachi-signature"];
const payload = JSON.stringify(req.body);
// Verify webhook signature
if (!verifySignature(payload, signature)) {
return res.status(400).send("Invalid signature");
}
// Process webhook
await processWebhook(req.body);
res.status(200).send("OK");
} catch (error) {
console.error("Webhook processing error:", error);
res.status(500).send("Internal Server Error");
}
});
Terminal window
# Regular cleanup
git gc --aggressive --prune=now
git remote prune origin
# Remove merged branches
git branch --merged | grep -v "\*\|main\|master" | xargs -n 1 git branch -d
# Update submodules
git submodule update --remote --merge
# Verify repository integrity
git fsck --full
  • Delete merged feature branches promptly
  • Use conventional commit messages
  • Regularly rebase long-running branches
  • Squash commits before merging to main
{
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"typescript.preferences.importModuleSpecifier": "relative",
"files.watcherExclude": {
"**/node_modules/**": true,
"**/.git/objects/**": true,
"**/dist/**": true
}
}
Terminal window
# NPM cache management
npm cache verify
npm cache clean --force
# Yarn cache management
yarn cache clean
# Clear global packages that aren't needed
npm ls -g --depth=0
npm uninstall -g unused-package
#!/bin/bash
# Monthly API key rotation script
# Generate new API key
NEW_KEY=$(curl -X POST https://api.torosachi.com/v1/keys \
-H "Authorization: Bearer $CURRENT_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Production Key '$(date +%Y%m)'"}')
# Update environment variables
echo "TOROSACHI_API_KEY=$NEW_KEY" > .env.new
# Test new key
if curl -f https://api.torosachi.com/v1/account \
-H "Authorization: Bearer $NEW_KEY" > /dev/null 2>&1; then
mv .env.new .env
echo "API key rotated successfully"
# Revoke old key after grace period
sleep 300
curl -X DELETE https://api.torosachi.com/v1/keys/$OLD_KEY_ID \
-H "Authorization: Bearer $NEW_KEY"
else
echo "New API key test failed"
rm .env.new
exit 1
fi
Terminal window
# Check SSL certificate expiry
check_ssl_expiry() {
local domain=$1
local expiry_date=$(openssl s_client -servername $domain -connect $domain:443 2>/dev/null | \
openssl x509 -noout -dates | grep 'notAfter' | cut -d= -f2)
echo "SSL certificate for $domain expires: $expiry_date"
}
# Monitor important domains
check_ssl_expiry "api.torosachi.com"
check_ssl_expiry "your-domain.com"
Terminal window
# NPM security audit
npm audit --audit-level=moderate
# Update vulnerable packages
npm audit fix
# Check for known vulnerabilities
npx retire --js --node
# Scan for secrets in code
git secrets --scan
-- Identify slow queries
SELECT
query,
mean_time,
calls,
total_time
FROM pg_stat_statements
ORDER BY mean_time DESC
LIMIT 10;
-- Create necessary indexes
CREATE INDEX CONCURRENTLY idx_subscriptions_customer_status
ON subscriptions(customer_id, status)
WHERE status IN ('active', 'trialing');
-- Analyze query execution plans
EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM subscriptions
WHERE customer_id = 'customer_123'
AND status = 'active';
// Add performance monitoring
const performanceMiddleware = (req, res, next) => {
const start = Date.now();
res.on("finish", () => {
const duration = Date.now() - start;
console.log(`${req.method} ${req.path} - ${duration}ms`);
// Alert on slow requests
if (duration > 1000) {
console.warn(`Slow request detected: ${req.path} took ${duration}ms`);
}
});
next();
};
Terminal window
# Redis maintenance commands
redis-cli INFO memory
redis-cli INFO stats
# Clear expired keys
redis-cli SCAN 0 MATCH "expired:*" | xargs redis-cli DEL
# Monitor key expiration
redis-cli --latency-history -i 1
# Optimize memory usage
redis-cli CONFIG SET maxmemory-policy allkeys-lru
app.get("/health", async (req, res) => {
const health = {
status: "healthy",
timestamp: new Date().toISOString(),
checks: {},
};
try {
// Database connectivity
const dbResult = await db.query("SELECT 1");
health.checks.database = {
status: "healthy",
responseTime: dbResult.duration,
};
// External API connectivity
const apiStart = Date.now();
await fetch("https://api.torosachi.com/v1/health");
health.checks.externalAPI = {
status: "healthy",
responseTime: Date.now() - apiStart,
};
// Memory usage
const memoryUsage = process.memoryUsage();
health.checks.memory = {
status: memoryUsage.heapUsed < 1000000000 ? "healthy" : "warning",
heapUsed: memoryUsage.heapUsed,
heapTotal: memoryUsage.heapTotal,
};
res.status(200).json(health);
} catch (error) {
health.status = "unhealthy";
health.error = error.message;
res.status(503).json(health);
}
});
Terminal window
# Logrotate configuration
/var/log/torosachi/*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
create 0644 www-data www-data
postrotate
/bin/kill -USR1 $(cat /var/run/nodejs.pid) 2>/dev/null || true
endscript
}
# Log analysis for common patterns
grep "ERROR" /var/log/torosachi/app.log | tail -10
grep "webhook.*failed" /var/log/torosachi/app.log | wc -l
awk '/payment.*failed/ {print $1, $2, $NF}' /var/log/torosachi/app.log
#!/bin/bash
# Monthly backup restore test
TEST_DB="torosachi_test_restore"
BACKUP_FILE="/backups/database/latest.sql.gz"
# Create test database
createdb $TEST_DB
# Restore from backup
gunzip -c $BACKUP_FILE | psql $TEST_DB
# Verify data integrity
RECORD_COUNT=$(psql $TEST_DB -t -c "SELECT COUNT(*) FROM subscriptions")
EXPECTED_COUNT=1000 # Adjust based on your data
if [ $RECORD_COUNT -ge $EXPECTED_COUNT ]; then
echo "Backup restore test passed: $RECORD_COUNT records found"
else
echo "Backup restore test failed: only $RECORD_COUNT records found"
exit 1
fi
# Cleanup
dropdb $TEST_DB
  1. Immediate Response (0-5 minutes)

    • Confirm service outage
    • Check infrastructure status
    • Activate incident response team
    • Switch to maintenance mode
  2. Investigation (5-15 minutes)

    • Review recent deployments
    • Check error logs
    • Verify database connectivity
    • Test external dependencies
  3. Recovery (15-60 minutes)

    • Apply fixes or rollback
    • Verify service restoration
    • Monitor key metrics
    • Communicate status updates
  4. Post-Incident Follow-Up

    • Conduct post-mortem
    • Update runbooks
    • Implement preventive measures
    • Document lessons learned
# docker-compose.yml for consistent environments
version: "3.8"
services:
app:
image: node:18-alpine
environment:
- NODE_ENV=production
- TOROSACHI_API_KEY=${TOROSACHI_API_KEY}
volumes:
- ./app:/app
ports:
- "3000:3000"
redis:
image: redis:7-alpine
command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
postgres:
image: postgres:15-alpine
environment:
- POSTGRES_DB=torosachi
- POSTGRES_USER=app
- POSTGRES_PASSWORD=${DB_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:

Keep updated documentation for:

  • Infrastructure topology diagrams
  • API integration specifications
  • Incident response procedures
  • Recovery time objectives (RTO)
  • Recovery point objectives (RPO)
  • Contact information for vendors
  • Escalation procedures

Regular maintenance is the key to reliable subscription management systems. Review this guide monthly and update procedures as your infrastructure evolves.