[ PROMPT_NODE_25315 ]
Service Types
[ SKILL_DOCUMENTATION ]
# Render Service Types
Detailed explanation of each service type available on Render. Choose the right service type based on your application's needs.
## Web Services (`type: web`)
### Purpose
Web services are HTTP servers that handle incoming requests from the internet. They're publicly accessible via HTTPS URLs.
### Use Cases
- **REST APIs**: JSON APIs for mobile apps or frontend applications
- **GraphQL servers**: GraphQL endpoints for client queries
- **Web applications**: Server-rendered websites (Django, Rails, Express)
- **Full-stack frameworks**: Next.js, Nuxt.js, Remix, SvelteKit
- **WebSocket servers**: Real-time communication servers
- **SSR applications**: Server-side rendered React, Vue, or Angular apps
### Key Characteristics
- **Public URL**: Automatically assigned `https://[service-name].onrender.com`
- **Port binding required**: Must bind to `0.0.0.0:$PORT`
- **Health checks**: Render pings your service to verify it's running
- **HTTPS**: Automatic SSL/TLS certificates
- **Load balancing**: Traffic distributed across multiple instances
- **Custom domains**: Support for your own domain names
### Required Configuration
```yaml
type: web
name: my-api
runtime: node
buildCommand: npm ci
startCommand: npm start
```
### Best Practices
1. **Bind to environment PORT**:
```javascript
const PORT = process.env.PORT || 3000;
app.listen(PORT, '0.0.0.0');
```
2. **Add health check endpoint**:
```javascript
app.get('/health', (req, res) => {
res.status(200).json({ status: 'ok' });
});
```
3. **Use appropriate timeouts**: Web requests should complete within 30 seconds
4. **Implement graceful shutdown**: Handle SIGTERM signals properly
---
## Worker Services (`type: worker`)
### Purpose
Worker services run background tasks without handling HTTP requests. They're not publicly accessible.
### Use Cases
- **Queue processors**: Redis queue, BullMQ, Celery, Sidekiq
- **Background jobs**: Email sending, image processing, data exports
- **Event consumers**: Message queue consumers (Kafka, RabbitMQ, etc.)
- **Data pipeline workers**: ETL processes, data transformation
- **Scheduled background tasks**: Continuous processes (not cron)
- **WebSocket backend**: Dedicated WebSocket handler services
### Key Characteristics
- **No public URL**: Not accessible from internet
- **No port binding**: Doesn't need to listen on a port
- **No health checks**: Render monitors process health differently
- **Long-running**: Can run indefinitely
- **Private communication**: Access via internal networking
- **Restart on crash**: Automatically restarted if process dies
### Required Configuration
```yaml
type: worker
name: queue-processor
runtime: python
buildCommand: pip install -r requirements.txt
startCommand: celery -A tasks worker --loglevel=info
```
### Best Practices
1. **Connect to message queue**:
```python
import redis
r = redis.from_url(os.environ['REDIS_URL'])
```
2. **Implement retry logic**: Handle failures gracefully
3. **Monitor queue depth**: Track pending jobs
4. **Log processing status**: Make debugging easier
5. **Graceful shutdown**: Finish current jobs before exiting
### Common Patterns
**Node.js with BullMQ:**
```yaml
type: worker
name: job-processor
runtime: node
buildCommand: npm ci
startCommand: node worker.js
envVars:
- key: REDIS_URL
fromDatabase:
name: redis
property: connectionString
```
**Python with Celery:**
```yaml
type: worker
name: celery-worker
runtime: python
buildCommand: pip install -r requirements.txt
startCommand: celery -A app.celery worker
envVars:
- key: REDIS_URL
fromDatabase:
name: redis
property: connectionString
```
---
## Cron Jobs (`type: cron`)
### Purpose
Cron jobs run scheduled tasks on a repeating schedule. They execute, complete, and shut down.
### Use Cases
- **Database backups**: Regular automated backups
- **Report generation**: Daily/weekly reports
- **Data cleanup**: Delete old records periodically
- **Cache warming**: Pre-populate caches
- **Email digests**: Send scheduled email summaries
- **Data synchronization**: Sync between systems
- **Batch processing**: Process accumulated data
### Key Characteristics
- **Scheduled execution**: Runs on cron schedule
- **Automatic shutdown**: Shuts down after completing
- **No persistent port**: Doesn't maintain listening port
- **No health checks**: Task either completes or fails
- **UTC timezone**: All schedules in UTC
- **Maximum runtime**: Jobs timeout after configured limit
### Required Configuration
```yaml
type: cron
name: daily-backup
runtime: node
schedule: "0 2 * * *" # Daily at 2 AM UTC
buildCommand: npm ci
startCommand: node scripts/backup.js
```
### Schedule Format
Standard cron syntax: `minute hour day month weekday`
**Common schedules:**
| Schedule | Description |
|----------|-------------|
| `*/5 * * * *` | Every 5 minutes |
| `0 * * * *` | Every hour |
| `0 0 * * *` | Daily at midnight UTC |
| `0 9 * * 1-5` | Weekdays at 9 AM UTC |
| `0 0 1 * *` | First day of each month |
| `0 9 * * 1` | Every Monday at 9 AM UTC |
### Best Practices
1. **Handle failures gracefully**: Jobs should be idempotent
2. **Log completion status**: Track success/failure
3. **Set appropriate timeouts**: Match expected job duration
4. **Use UTC times**: All schedules are UTC-based
5. **Test thoroughly**: Test with different data scenarios
### Example Use Cases
**Daily Database Backup:**
```yaml
type: cron
name: db-backup
runtime: python
schedule: "0 1 * * *" # 1 AM UTC daily
buildCommand: pip install -r requirements.txt
startCommand: python scripts/backup.py
envVars:
- key: DATABASE_URL
fromDatabase:
name: postgres
property: connectionString
- key: S3_BUCKET
value: my-backups
```
**Hourly Cache Refresh:**
```yaml
type: cron
name: cache-refresh
runtime: node
schedule: "0 * * * *" # Top of every hour
buildCommand: npm ci
startCommand: node scripts/refresh-cache.js
```
---
## Static Sites (`type: web` + `runtime: static`)
### Purpose
Serve static HTML, CSS, and JavaScript files via CDN. No backend runtime.
### Use Cases
- **Single Page Applications (SPAs)**: React, Vue, Angular apps
- **Static site generators**: Gatsby, Next.js (static export), Hugo
- **Documentation sites**: MkDocs, Docusaurus, VitePress
- **Landing pages**: Marketing sites
- **Portfolio sites**: Personal websites
- **JAMstack sites**: Static sites with API integration
### Key Characteristics
- **CDN delivery**: Global edge caching
- **No backend runtime**: Only serves built files
- **Build output only**: Serves contents of build directory
- **Routing support**: Rewrite rules for SPA routing
- **Custom headers**: Cache control, security headers
- **Fast deployment**: Quick to build and deploy
### Required Configuration
```yaml
type: web
name: frontend
runtime: static
buildCommand: npm ci && npm run build
staticPublishPath: ./dist # or ./build, ./out, ./public
```
### Routing for SPAs
Single Page Applications need rewrite rules to handle client-side routing:
```yaml
type: web
name: react-app
runtime: static
buildCommand: npm ci && npm run build
staticPublishPath: ./build
routes:
- type: rewrite
source: /*
destination: /index.html
```
### Custom Headers
Add cache control and security headers:
```yaml
type: web
name: static-site
runtime: static
buildCommand: npm ci && npm run build
staticPublishPath: ./dist
headers:
# Cache static assets
- path: /static/*
name: Cache-Control
value: public, max-age=31536000, immutable
# Security headers
- path: /*
name: X-Frame-Options
value: DENY
- path: /*
name: X-Content-Type-Options
value: nosniff
```
### Build Filters
For monorepos, only build when frontend files change:
```yaml
type: web
name: frontend
runtime: static
buildCommand: npm ci && npm run build
staticPublishPath: ./dist
buildFilter:
paths:
- frontend/**
ignoredPaths:
- frontend/**/*.test.js
- frontend/README.md
```
### Best Practices
1. **Optimize build output**: Minify, compress, tree-shake
2. **Use proper cache headers**: Long cache for hashed assets
3. **Add security headers**: Protect against common attacks
4. **Configure SPA routing**: Add rewrite rules for client routing
5. **Handle 404s**: Create custom 404.html page
---
## Private Services (`type: pserv`)
### Purpose
Internal services accessible only within your Render account. Not exposed to the internet.
### Use Cases
- **Internal APIs**: Services accessed only by other services
- **Database proxies**: Connection pools, read replicas
- **Microservices**: Service mesh architectures
- **Admin tools**: Internal dashboards
- **Cache layers**: Internal caching services
- **Message brokers**: Internal message queues
### Key Characteristics
- **No public URL**: Only accessible via internal DNS
- **Internal networking**: Fast, low-latency connections
- **Port binding required**: Must bind to `0.0.0.0:$PORT`
- **Private DNS**: `[service-name].render-internal.com`
- **Same-account only**: Only accessible from same account
- **No internet access**: Traffic stays within Render network
### Required Configuration
```yaml
type: pserv
name: internal-api
runtime: node
buildCommand: npm ci
startCommand: npm start
```
### Accessing Private Services
From other services in the same account:
```javascript
// Use .render-internal.com domain
const API_URL = 'http://internal-api.render-internal.com:10000';
```
Or use service references:
```yaml
services:
- type: web
name: frontend
runtime: node
envVars:
- key: INTERNAL_API_URL
fromService:
name: internal-api
type: pserv
property: hostport
```
### Best Practices
1. **Use internal DNS**: Always use `.render-internal.com` domains
2. **No authentication needed**: Already isolated to account
3. **Fast communication**: Low latency between services
4. **Simplify architecture**: No need for external load balancers
---
## Comparison Table
| Feature | Web | Worker | Cron | Static | Private |
|---------|-----|--------|------|--------|---------|
| Public URL | ✅ Yes | ❌ No | ❌ No | ✅ Yes | ❌ No |
| Port Binding | ✅ Required | ❌ Not needed | ❌ Not needed | ❌ N/A | ✅ Required |
| Health Checks | ✅ Yes | ❌ No | ❌ No | ❌ N/A | ✅ Yes |
| Runtime | ✅ Yes | ✅ Yes | ✅ Yes | ❌ No | ✅ Yes |
| Persistent | ✅ Yes | ✅ Yes | ❌ No | ✅ Yes | ✅ Yes |
| Scaling | ✅ Yes | ✅ Yes | ❌ No | ✅ Yes | ✅ Yes |
| Use Case | HTTP servers | Background jobs | Scheduled tasks | Static files | Internal services |
## Choosing the Right Service Type
**Use Web Service when:**
- Your app handles HTTP requests
- Users need to access it via URL
- You need load balancing and scaling
**Use Worker Service when:**
- Processing background jobs
- Consuming from message queues
- Running long-lived processes without HTTP
**Use Cron Job when:**
- Running scheduled tasks
- Processing doesn't need to be always-on
- Tasks run periodically (hourly, daily, weekly)
**Use Static Site when:**
- Serving pre-built HTML/CSS/JS
- No backend processing needed
- Want CDN caching and fast delivery
**Use Private Service when:**
- Service only accessed by other services
- Want internal-only communication
- Building microservice architectures
Source: claude-code-templates (MIT). See About Us for full credits.