Skip to content

Getting-Started Assessment (L1 + L2)

Covers setup and the system overview. Checkpoint for Week 1 of the Learning Path. Grading: see Assessments README. Pass = 80% on MCQs.

Part A — L1 Multiple Choice

1. Prism consists of how many deployables, and what are they? - a) One monolith only - b) Two: uengage-crm (Express monolith) + prism-services (serverless) - c) Three microservices - d) A monolith + a mobile app

Answer**b.** `uengage-crm` is the long-running Express monolith (PM2); `prism-services` is AWS Lambda + Kafka. They share one MongoDB `uengage` database.

2. Which collection is the "seam" between the monolith and the serverless tier? - a) orders_dump b) crm_queue c) business_configs d) dashboard_mis

Answer**b. `crm_queue`.** Both the `orders-consumer` Lambda and the monolith's ingestion controllers write to it; crons drain it.

3. How many crons run, and where do they run? - a) ~91, in a separate worker service - b) ~91, in-process inside the web server (registered at startup in index.js) - c) 12, via cron.d on the host - d) None; everything is event-driven

Answer**b.** All ~91 crons are `require()`d at startup and run in the same process as the API — which is why a heavy cron can affect API latency.

4. Why does MySQL have two connection pools (webPool 15, jobsPool 10)? - a) One for reads, one for writes - b) So background crons never starve web request traffic - c) One for MongoDB, one for MySQL - d) For A/B testing

Answer**b.** Separate pools isolate cron/job DB load from request handlers. Monitored by `utilities/poolMonitor.js` (`pool_stats` every 60s).

5. The MongoDB client is configured with: - a) maxPoolSize 400, readPreference SECONDARY_PREFERRED - b) maxPoolSize 10, PRIMARY - c) maxPoolSize 50, NEAREST - d) default settings

Answer**a.** DB name is hardcoded `uengage`; both native driver + Mongoose are used.

6. What is the universal customer join key across MongoDB and MySQL? - a) email b) _id c) the 10-digit mobile number d) customer_id UUID

Answer**c.** The 10-digit Indian mobile number (no country code) joins customer data across both stores.

7. The tenant scope on almost every query is: - a) user_id b) parent_business_id + child_business_id c) region d) outlet_name

Answer**b.** Parent = brand/HQ, child = outlet. Multi-tenancy isolation.

8. Which Kafka topic carries incoming orders? - a) orders b) prism-ingest-orders c) crm-orders d) ingest

Answer**b. `prism-ingest-orders`** — produced by `orders-api` λ, consumed by `orders-consumer` λ (batch 10) which writes `crm_queue`.

9. The WhatsApp Kafka consumers (consumer-send, consumer-receipts) currently: - a) Send messages and persist receipts - b) Are stubbed — log only, no DB writes - c) Do not exist - d) Write directly to MySQL

Answer**b.** They are log-only stubs; the monolith's own WhatsApp crons do the real work today.

10. On boot, if MongoDB is unreachable, the monolith: - a) retries forever b) starts anyway c) process.exit(1) d) falls back to MySQL

Answer**c.** Mongo failure exits the process; Redis failure only logs and continues.

11. How many auth middlewares does the monolith have? - a) 1 b) 3 c) 6 d) 12

Answer**c. Six:** `authMiddleware`, `adminMiddleware`, `appMiddleware`, `jwtMiddleware`/`jwtWhatsappMiddleware`, `crm_offer_middleware`, `injestion_middleware`/`thirdPartyMiddleware`.

12. Which command runs the monolith in local dev? - a) npm start b) npm run start:dev (NODE_ENV=dev nodemon index.js) c) pm2 start d) serverless offline

Answer**b.** `start`/`start:prod` run `NODE_ENV=prod node index.js`.

13. What surprising thing is committed to the repo (a security smell)? - a) node_modules b) .env.dev c) production DB dumps d) AWS keys in README

Answer**b.** A committed `.env.dev` (loaded when `NODE_ENV=dev`) eases bootstrap but is a security smell. Redis host is also hardcoded in `utilities/redis.js`.

14. Which datastore holds the loyalty wallet, wallet_history, and wallet_rules? - a) MongoDB b) MySQL (addo_*) c) Redis d) Kafka

Answer**b. MySQL.** Money & identity live in MySQL; fast-changing buffers/MIS live in MongoDB.

15. crm_queue.status represents: - a) HTTP status b) the ingestion state machine (e.g. 0 = queued, processed later) c) fraud score d) tenant id

Answer**b.** Producers insert `status:0`; crons drain and mark processed.

Part B — L2 Scenarios

S1. You start the monolith locally and your laptop fan spins up immediately; CPU is pinned even with no traffic. What is the most likely cause and the sanctioned fix?

AnswerAll ~91 crons register at startup and run in-process, so they begin hammering the DB immediately. The sanctioned fix is to **comment out the heavy crons in `index.js`** (there's a comment marking them) for local dev — and **never point local crons at production DBs**. See [Local-Setup §4](../00-Getting-Started/Local-Setup.md).

S2. A teammate says "just add the order straight to MySQL from the ingestion endpoint." Why is that wrong, and what actually happens to an ingested order?

AnswerIngestion is **fire-and-forget**: the endpoint inserts into `crm_queue` (`status:0`) and returns 200; the real work (customer upsert, order write, LTV/LTO/AOV recompute, points enqueue, journeys) happens **asynchronously in crons**. Writing MySQL synchronously bypasses the queue, breaks the dual-ingestion contract, and couples request latency to heavy processing. See [System-Overview §5](../00-Getting-Started/System-Overview.md).

S3. Redis connection errors are spamming your local logs but the app keeps running. Explain both observations.

Answer`utilities/redis.js` **hardcodes an AWS ElastiCache host** that's unreachable from your laptop → connection errors. The app keeps running because **Redis failure only logs and continues** (unlike Mongo, which exits). Fix locally by temporarily pointing it at `127.0.0.1:6379` (don't commit). See [Local-Setup §3/§8](../00-Getting-Started/Local-Setup.md).