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?
Answer
All ~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?
Answer
Ingestion 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.