Retrospring is a self-hosted anonymous Q&A platform — think Curious Cat or Formspring, but running entirely on your own server. Built on Ruby on Rails with Puma, PostgreSQL, Redis, and Sidekiq, it has several interdependent services that must all be healthy for anonymous questions to flow, notifications to arrive, and media to upload. Vigilmon watches the whole stack externally so you know the moment any layer breaks.
What You'll Set Up
- HTTP uptime monitor for the Puma/Rails application
- Health check endpoint covering PostgreSQL, Redis, and Sidekiq
- Anonymous submission endpoint response time monitoring
- Sidekiq background job worker heartbeat
- WebSocket notification endpoint check
- SSL certificate expiry alerts
- Scheduled analytics/cleanup job heartbeat
Prerequisites
- Retrospring deployed on a VPS (Rails + Puma, port 3000 typically proxied via nginx)
- PostgreSQL database
- Redis + Sidekiq for background jobs
- A free Vigilmon account
Step 1: Monitor Web Server Availability
Retrospring's Puma server runs on port 3000, typically behind an nginx reverse proxy that handles SSL termination. Monitor the public-facing URL:
- Log in to vigilmon.online and click Add Monitor.
- Set Type to
HTTP / HTTPS. - Enter your instance URL:
https://retrospring.yourdomain.com - Set Check interval to
1 minute. - Set Expected HTTP status to
200. - Enable Monitor SSL certificate with a
21 dayexpiry alert. - Click Save.
Add a keyword check that verifies the Retrospring UI loads correctly:
- Under Keyword check, enter
retrospringor a string from your site's HTML title tag.
This catches the case where nginx returns 200 with an error page because Puma is down.
Step 2: Add a Rails Health Check Endpoint
Rails 7.1+ includes a built-in health check at /up. If you're running an older version, or want a more detailed check, add a custom health endpoint.
For Rails 7.1+, the /up endpoint is available by default:
https://retrospring.yourdomain.com/up
Add a Vigilmon monitor for /up with a 1-minute interval and expected status 200.
For a detailed health check covering all dependencies, add a custom controller. In config/routes.rb:
get '/health', to: 'health#show'
Create app/controllers/health_controller.rb:
class HealthController < ApplicationController
skip_before_action :authenticate_user!, raise: false
skip_before_action :verify_authenticity_token
def show
checks = {
database: check_database,
redis: check_redis,
sidekiq: check_sidekiq,
}
status = checks.values.all? { |v| v == 'ok' } ? :ok : :service_unavailable
render json: { status: status, checks: checks }, status: status
end
private
def check_database
ActiveRecord::Base.connection.execute('SELECT 1')
'ok'
rescue => e
Rails.logger.error("Health check DB failed: #{e.message}")
'error'
end
def check_redis
Redis.new.ping == 'PONG' ? 'ok' : 'error'
rescue => e
Rails.logger.error("Health check Redis failed: #{e.message}")
'error'
end
def check_sidekiq
stats = Sidekiq::Stats.new
# Alert if the dead queue is growing or retry queue is large
stats.dead_size < 100 ? 'ok' : 'warn'
rescue => e
'error'
end
end
Deploy and add a Vigilmon HTTP monitor for https://retrospring.yourdomain.com/health.
Step 3: Monitor the Anonymous Submission Endpoint
The anonymous question submission form is Retrospring's core feature. Monitor it explicitly so you know if the submission endpoint stops accepting requests:
- In Vigilmon, click Add Monitor → HTTP / HTTPS.
- Enter:
https://retrospring.yourdomain.com/ajax/ask - Set Expected HTTP status to
401or422— unauthenticated GET requests to a POST endpoint return an error code, which still confirms the endpoint is alive. - Set Check interval to
5 minutes. - Click Save.
Alternatively, add a response time threshold: if submission response time exceeds 2 seconds, something is wrong with the database or job queue backing the endpoint.
Step 4: Heartbeat Monitoring for Sidekiq Workers
Sidekiq processes email notifications, question inbox delivery, and other background tasks. If Sidekiq stops, your users won't receive notifications even though the web app appears healthy.
Add a Sidekiq middleware that pings a Vigilmon heartbeat after each successful job batch.
Create config/initializers/vigilmon_heartbeat.rb:
# Ping Vigilmon after every Sidekiq queue drain cycle
class VigilmonSidekiqMiddleware
HEARTBEAT_URL = ENV['VIGILMON_SIDEKIQ_HEARTBEAT_URL']
PING_INTERVAL = 5.minutes
def call(worker, job, queue)
result = yield
if HEARTBEAT_URL.present? && should_ping?
Net::HTTP.get(URI(HEARTBEAT_URL)) rescue nil
end
result
end
private
def should_ping?
now = Time.now.to_i
last = Rails.cache.read('vigilmon_last_ping').to_i
if now - last > PING_INTERVAL
Rails.cache.write('vigilmon_last_ping', now, expires_in: 10.minutes)
true
else
false
end
end
end
Sidekiq.configure_server do |config|
config.server_middleware do |chain|
chain.add VigilmonSidekiqMiddleware
end
end
Add VIGILMON_SIDEKIQ_HEARTBEAT_URL to your .env or Rails credentials.
In Vigilmon, create a Cron Heartbeat monitor with a 10 minute expected interval. If Sidekiq crashes or the queue stops draining, the heartbeat stops and Vigilmon alerts.
Step 5: Monitor WebSocket Notifications
Retrospring uses WebSocket connections for real-time question notifications. The WebSocket endpoint is typically at /cable. Monitor it so you catch nginx/Puma misconfiguration that breaks real-time features post-deploy:
- In Vigilmon, add an HTTP monitor for
https://retrospring.yourdomain.com/cable. - Set Expected HTTP status to
101(WebSocket upgrade) or400(bad WebSocket request) — either confirms the endpoint is routing correctly. - Set Check interval to
5 minutes.
If your nginx configuration strips the Upgrade header, this check returns 400 rather than 101, and both are acceptable to confirm the endpoint is alive.
Step 6: Heartbeat for Scheduled Analytics and Cleanup Jobs
Retrospring runs scheduled tasks for analytics aggregation and old data cleanup. Use Sidekiq-Cron or whenever for scheduling; wrap each critical job in a heartbeat ping.
If using whenever (config/schedule.rb):
every 1.day, at: '2:00 AM' do
rake 'retrospring:cleanup_old_questions'
end
Modify the rake task to ping after completion:
# lib/tasks/retrospring.rake
namespace :retrospring do
desc 'Clean up expired questions and analytics data'
task cleanup_old_questions: :environment do
# ... cleanup logic ...
heartbeat_url = ENV['VIGILMON_CLEANUP_HEARTBEAT_URL']
Net::HTTP.get(URI(heartbeat_url)) if heartbeat_url.present?
end
end
Create a Vigilmon Cron Heartbeat with a 25 hour expected interval for daily jobs.
Step 7: Configure Alert Channels
- Go to Alert Channels in Vigilmon and add your email or Slack webhook.
- On the main web monitor and health endpoint, set Consecutive failures before alert to
2. - On the Sidekiq heartbeat, set Consecutive failures before alert to
1— a stopped worker queue deserves immediate attention. - Enable Maintenance windows in Vigilmon and automate them in your deployment script to suppress alerts during deploys:
# Before deploy
curl -X POST https://vigilmon.online/api/maintenance \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"monitor_id": "MONITOR_ID", "duration_minutes": 10}'
bundle exec cap production deploy
# Window expires automatically
Summary
| Monitor | Target | What It Catches |
|---|---|---|
| Web availability | https://retrospring.yourdomain.com | Puma crash, nginx misconfiguration |
| Health endpoint | /health or /up | DB down, Redis down, Sidekiq dead queue growing |
| Submission endpoint | /ajax/ask | Anonymous Q&A intake broken |
| Sidekiq heartbeat | Vigilmon heartbeat URL | Background job worker stopped |
| WebSocket endpoint | /cable | Real-time notifications broken |
| Cleanup job heartbeat | Vigilmon heartbeat URL | Scheduled maintenance failed |
| SSL certificate | Main domain | TLS certificate expired |
Retrospring's anonymous Q&A experience depends on fast submissions, reliable notifications, and background jobs that run on schedule. With Vigilmon monitoring every layer — from the Puma process to Sidekiq workers to WebSocket connectivity — you'll catch failures before users notice the silence.
Get started free at vigilmon.online.