The context
Iglesia Dios Fuerte Arca Evangélica needed to organize its weekly service programs — who leads, who worships, who preaches, who cleans — without relying on a spreadsheet or a coordinator's memory. The system, Church Program Manager, already existed in a first version (v1), but had real underlying problems that this project (v2) set out to fix at the root.
The challenge
v1 had a critical bug in the assignment engine: the fairness algorithm didn't correctly
prioritize people with less recent participation, and it also generated N+1 database queries on
every calculation. On top of that, there was a serious security gap for a system handling data
from multiple churches: the churchId could arrive tampered with from the request body
instead of always being derived from the authentication token — meaning nothing in the code
prevented one church from seeing or modifying another church's data.
The solution
v2 was a rewrite focused on security, correctness, and automation, not cosmetic features:
- Tenant Guard — middleware that forces the
churchIdto always come from the JWT, never from the body, and verifies the church is active against the database (with a 5-minute Redis cache so that check doesn't cost an extra query on every request). - 6-role RBAC — a SUPER_ADMIN > PASTOR > ADMIN > MINISTRY_LEADER > EDITOR > VIEWER hierarchy, enforced at the middleware level on every route.
- AssignmentEngine v2 — the assignment engine was split into a
FairnessCalculator(a normalized 3-component score, where lower recent participation now correctly means higher priority) and aHistoryAnalyzerthat preloads history into memory before calculating, eliminating v1's N+1 antipattern. - Redis cache with fallback — if Redis isn't available, the system automatically falls back to an in-memory Map instead of failing.
- Asynchronous notifications — Bull + Redis queues to send email and WhatsApp reminders 48 hours before each service, triggered when a program is published.
- PDF generation — Puppeteer + Handlebars templates to export the program with each church's logo, brand colors, and pastor's signature, with a watermark on the free plan.
The most interesting technical challenge: real multi-tenant isolation
In a system serving multiple churches from the same database, the line between "my data" and
"another church's data" can't depend on the client sending the right value — it has to be
guaranteed on the server, always. Tenant Guard solves this by overwriting any
churchId that arrives in the request body with the one signed into the JWT, and it
also validates against the database that the church is active before letting the request through
— with caching so that validation doesn't cost an extra query on every request. It's the
difference between "trusting the client" and "verifying on the server," applied consistently
through a single middleware at every endpoint, not case by case.
Key features
- Automatic assignment engine with a corrected fairness algorithm and no N+1 queries
- Multi-tenant security with Tenant Guard and 6-role RBAC
- PDF generation for programs with dynamic per-church branding (logo, colors, signature)
- Automatic email and WhatsApp reminders 48h before each service
- Management of people, ministries, roles, and recurring activities
- Invitation letter system with a step-by-step wizard and PDF export
- Dashboard with metrics and direct program downloads
- Per-church plans (FREE / PRO / ENTERPRISE) with configurable limits
System screenshots
Tech stack
Backend: Node.js · TypeScript · MongoDB · Redis · Bull · Puppeteer · Handlebars · JWT
Frontend: React · Vite · TypeScript