---
title: "Ebube Mba (@techgoodness) | Hashnode"
description: "Backend-focused Full-Stack Python Engineer and Systems Administrator with 9 years in IT operations and 5+ years engineering production software. Architected..."
url: "https://hashnode.com/@techgoodness"
---

@techgoodness

# Ebube Mba

@techgoodness · Abuja, Nigeria · Joined October 2026

## Comments

[Thanks for the thoughtful feedback! You hit right on some of the biggest tradeoffs we had to weigh when choosing JSONB. Regarding the mid-term rubric edits: you are 100% right that arbitrary tenant edits would break historical data. To protect against this, we actually don't expose the blueprint configuration to the school admins in the UI. The assessment blueprint is configured exclusively by our dev team during onboarding. Schools don't change their grading rubrics arbitrarily and if they do need a structural overhaul, it's handled as a supervised, scheduled migration by the engineering team between academic sessions, precisely because it is a destructive action. That being said, I really love your idea of storing a blueprint version (or a lightweight snapshot hash) alongside the Result payload. Even with dev-controlled blueprints, a school might legitimately change their policy from a 4-tier to a 5-tier assessment system three years from now. A version stamp would guarantee that historical report cards remain mathematically reproducible decades later without needing complex temporal tables. On the database constraints and GIN indexing: this is the classic JSONB tradeoff! Because we lose DB-level schema enforcement, we rely heavily on application-level validation (Django forms/validation logic) to strictly sanitize the payload before insertion. As for indexing, we intentionally lift the most heavily queried and ranked data out of the JSON. For example, total\_score and average\_score are explicitly stored as DecimalFields on the Result model, allowing us to use standard B-Tree indexes and native ORM aggregations. The JSONB field is primarily treated as a storage/presentation mechanism rather than a deep query target, though adding a GIN index is absolutely the next logical step if we ever need to run analytics on specific sub-scores (like isolating 'homework' trends across a district). Really appreciate the insights. Definitely adding the versioning snapshot idea to the roadmap!"](https://hashnode.com/posts/architecting-multi-tenant-django-saas-1800-users/6ad4e492097b8b8914fdac8b/comment/6adf88feced913dfcfc7129f#reply-6adf9eb053ea3fe1a14f3d54)

Reply · Article · Oct 26 · [From Bare-Metal Infrastructure to Multi-Tenant SaaS: Architecting a Django Platform for 1,800+ Users](https://hashnode.com/posts/architecting-multi-tenant-django-saas-1800-users/6ad4e492097b8b8914fdac8b)

[A testament to your unwaivering dedication and commitment to providing solutions. This is a great solutions that relieves schools of administrative and academic headache](https://hashnode.com/posts/architecting-multi-tenant-django-saas-1800-users/6ad4e492097b8b8914fdac8b/comment/6ad4e5fb2dc0fc02e8bc414f)

Comment · Article · Oct 18 · [From Bare-Metal Infrastructure to Multi-Tenant SaaS: Architecting a Django Platform for 1,800+ Users](https://hashnode.com/posts/architecting-multi-tenant-django-saas-1800-users/6ad4e492097b8b8914fdac8b)
