This guide covers deploying Vend to production environments.
- Alchemy API key configured (paid plan recommended)
- Payment wallet address set
- Environment variables secured
- Payment verification implemented
- Tests passing
- HTTPS/SSL configured
- Domain name registered (optional)
- Monitoring setup
Vercel offers:
- Free tier for personal projects
- Automatic HTTPS
- Global CDN
- Zero configuration
-
Install Vercel CLI
npm i -g vercel
-
Create
vercel.json{ "version": 2, "builds": [ { "src": "src/index.js", "use": "@vercel/node" } ], "routes": [ { "src": "/(.*)", "dest": "src/index.js" } ], "env": { "NODE_ENV": "production" } } -
Deploy
vercel
-
Set Environment Variables
vercel env add ALCHEMY_API_KEY vercel env add PAYMENT_ADDRESS vercel env add ALCHEMY_NETWORK vercel env add PAYMENT_NETWORK
Or via dashboard: vercel.com/dashboard
-
Deploy to Production
vercel --prod
vercel domains add vend.yourdomain.comHeroku provides:
- Simple git-based deployment
- Free tier (with limitations)
- Add-ons ecosystem
- Easy scaling
-
Install Heroku CLI
curl https://cli-assets.heroku.com/install.sh | sh -
Login
heroku login
-
Create App
heroku create vend-api
-
Set Environment Variables
heroku config:set ALCHEMY_API_KEY=your_key heroku config:set PAYMENT_ADDRESS=0x... heroku config:set ALCHEMY_NETWORK=eth-mainnet heroku config:set PAYMENT_NETWORK=base-mainnet heroku config:set NODE_ENV=production
-
Create
Procfileweb: npm start -
Deploy
git push heroku main
-
View Logs
heroku logs --tail
Deploy anywhere with Docker support (AWS, GCP, Azure, DigitalOcean).
# Dockerfile
FROM node:18-alpine
WORKDIR /app
# Copy package files
COPY package*.json ./
# Install dependencies
RUN npm ci --production
# Copy source code
COPY src ./src
# Expose port
EXPOSE 3000
# Set environment
ENV NODE_ENV=production
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD node -e "require('http').get('http://localhost:3000/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"
# Start server
CMD ["npm", "start"]node_modules
npm-debug.log
.env
.git
.gitignore
README.md
tests
docs
.DS_Store
# Build image
docker build -t vend .
# Run locally
docker run -p 3000:3000 \
-e ALCHEMY_API_KEY=your_key \
-e PAYMENT_ADDRESS=0x... \
vend
# Test
curl http://localhost:3000/healthAWS ECR + ECS:
# Authenticate
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin <account>.dkr.ecr.us-east-1.amazonaws.com
# Tag
docker tag vend:latest <account>.dkr.ecr.us-east-1.amazonaws.com/vend:latest
# Push
docker push <account>.dkr.ecr.us-east-1.amazonaws.com/vend:latest
# Deploy via ECS console or CLIGoogle Cloud Run:
# Build and deploy
gcloud run deploy vend \
--source . \
--platform managed \
--region us-central1 \
--allow-unauthenticated \
--set-env-vars ALCHEMY_API_KEY=your_key,PAYMENT_ADDRESS=0x...For full control with a virtual private server.
-
Provision Server
- Ubuntu 22.04 LTS
- 1GB RAM minimum
- SSH access
-
Install Node.js
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - sudo apt-get install -y nodejs -
Clone Repository
git clone https://github.com/yourusername/vend.git cd vend npm install --production -
Setup Environment
cp .env.example .env nano .env # Fill in values -
Install PM2
sudo npm install -g pm2
-
Start with PM2
pm2 start src/index.js --name vend pm2 save pm2 startup # Follow instructions -
Setup Nginx Reverse Proxy
sudo apt install nginx
Create
/etc/nginx/sites-available/vend:server { listen 80; server_name vend.yourdomain.com; location / { proxy_pass http://localhost:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } }
Enable site:
sudo ln -s /etc/nginx/sites-available/vend /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginx
-
Setup SSL with Let's Encrypt
sudo apt install certbot python3-certbot-nginx sudo certbot --nginx -d vend.yourdomain.com
# Required
ALCHEMY_API_KEY=your_production_key
PAYMENT_ADDRESS=0xYourProductionWallet
# Network settings
ALCHEMY_NETWORK=eth-mainnet
PAYMENT_NETWORK=base-mainnet
# Server
NODE_ENV=production
PORT=3000
# Logging
LOG_LEVEL=info
# Payment
PAYMENT_PRICE_PER_QUERY=0.01
X402_FACILITATOR_URL=https://x402.coinbase.com-
Enable HTTPS Only
// src/index.js if (config.nodeEnv === 'production') { app.use((req, res, next) => { if (req.header('x-forwarded-proto') !== 'https') { res.redirect(`https://${req.header('host')}${req.url}`); } else { next(); } }); }
-
Add Security Headers
npm install helmet
import helmet from 'helmet'; app.use(helmet());
-
Rate Limiting
npm install express-rate-limit
import rateLimit from 'express-rate-limit'; const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 100, // 100 requests per window }); app.use('/api/', limiter);
-
Validate Inputs
import { ethers } from 'ethers'; function validateAddress(address) { if (!ethers.utils.isAddress(address)) { throw new Error('Invalid Ethereum address'); } }
Use services like:
Monitor:
GET /healthendpoint- Response time < 2s
- 99.9% uptime target
Sentry for Error Tracking:
npm install @sentry/node// src/index.js
import * as Sentry from '@sentry/node';
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: config.nodeEnv,
});
app.use(Sentry.Handlers.errorHandler());LogDNA/Datadog for Logs:
Configure log shipping from Pino:
// src/logger.js
export const logger = pino({
level: config.logLevel,
formatters: {
level: (label) => ({ level: label }),
},
});Track:
- Request count
- Response time
- Error rate
- Payment success rate
- Alchemy API usage
Example with Prometheus:
npm install prom-clientimport client from 'prom-client';
const register = new client.Registry();
const httpRequestDuration = new client.Histogram({
name: 'http_request_duration_seconds',
help: 'Duration of HTTP requests in seconds',
labelNames: ['method', 'route', 'status'],
registers: [register],
});
app.get('/metrics', async (req, res) => {
res.set('Content-Type', register.contentType);
res.end(await register.metrics());
});Run multiple instances:
PM2:
pm2 start src/index.js -i max # Use all CPU coresDocker Compose:
version: '3'
services:
vend:
image: vend:latest
deploy:
replicas: 4
environment:
- ALCHEMY_API_KEY
- PAYMENT_ADDRESSLoad Balancer:
- Nginx
- HAProxy
- Cloud load balancers (ALB, GCP LB, etc.)
Add Redis for payment verification cache:
npm install redisimport { createClient } from 'redis';
const redis = createClient({ url: process.env.REDIS_URL });
async function verifyPayment(paymentHash) {
// Check cache
const cached = await redis.get(`payment:${paymentHash}`);
if (cached) return JSON.parse(cached);
// Verify
const isValid = await verifyPaymentOnChain(paymentHash);
// Cache result
await redis.setEx(`payment:${paymentHash}`, 3600, JSON.stringify(isValid));
return isValid;
}For storing payment records:
npm install pg # PostgreSQLimport pg from 'pg';
const pool = new pg.Pool({
connectionString: process.env.DATABASE_URL,
});
async function recordPayment(payment) {
await pool.query(
'INSERT INTO payments (hash, amount, address, timestamp) VALUES ($1, $2, $3, $4)',
[payment.hash, payment.amount, payment.address, new Date()]
);
}# PostgreSQL
pg_dump $DATABASE_URL > backup.sql
# Automated daily backups
0 2 * * * pg_dump $DATABASE_URL | gzip > /backups/vend-$(date +\%Y\%m\%d).sql.gzStore in version control (GitHub private repo):
- Environment variable templates
- Nginx configs
- PM2 configs
- Docker compose files
| Service | Tier | Cost/Month |
|---|---|---|
| Vercel | Hobby | $0 |
| Heroku | Eco Dyno | $5 |
| DigitalOcean | Droplet 1GB | $6 |
| AWS EC2 | t3.micro | ~$8 |
| Google Cloud Run | Pay-as-you-go | ~$5-20 |
| Service | Plan | Cost/Month |
|---|---|---|
| Alchemy | Free | $0 (limited) |
| Alchemy | Growth | $49+ |
| Redis | Upstash free | $0 |
| Monitoring | Free tier | $0 |
- Check if app is running:
pm2 status - Check logs:
pm2 logs vend - Verify port:
netstat -tlnp | grep 3000
- Enable Node.js memory limits:
node --max-old-space-size=512 src/index.js
- Upgrade plan
- Implement caching
- Add retry logic with backoff
# Pull latest code
git pull origin main
# Install dependencies
npm install
# Run tests
npm test
# Restart
pm2 restart vendDaily:
- Check error logs
- Verify uptime
- Monitor response times
Weekly:
- Review Alchemy usage
- Check payment success rate
- Update dependencies
Monthly:
- Security updates
- Cost review
- Performance optimization
Questions? Open an issue