Multi-Tenant Survey Platform
A Flask and Azure platform for running the same structured questionnaire across many organisational units at once — with role-based access, scheduled review rounds, progress tracking, and AI-generated summaries of what came back.
The problem it solves
Any organisation running a periodic assessment across a lot of separate units hits the same wall. The questionnaire goes out as a spreadsheet, comes back in forty inconsistent versions, and someone spends a fortnight reconciling them by hand. Nobody can see who has finished and who has not. Last cycle's answers are in someone's inbox.
This platform replaces that with one system: a structured questionnaire, per-unit access control, visible completion state, a formal review stage before anything is final, and an audit trail that survives the people who ran the last cycle.
Key Features
Role-Based Access
Authentication with distinct administrator and respondent roles, scoped so each participant sees only their own unit's questionnaire
Admin Portal
User and tenant management with a dashboard covering completion state, review status, and outstanding submissions
Configurable Questionnaires
Section-based questionnaire definitions, so more than one assessment type can run from a single deployment
Progress Tracking
Completion status tracked automatically per section, giving administrators live visibility without chasing anyone
Scheduled Review Rounds
Time-boxed review periods with their own configuration, so submissions are reviewed and returned rather than merely collected
Cosmos DB Storage
Azure Cosmos DB as the NoSQL backing store, partitioned so tenants scale independently of one another
AI-Generated Summaries
OpenAI integration turns raw responses into readable per-unit summary documents, removing the manual synthesis step
Document Management
Supporting files stored in Azure Blob Storage with categorisation and permissions enforced at user and role level
Automated Deployment
GitHub Actions pipeline deploying to Azure App Service, so releases are repeatable rather than hand-run
Technical Architecture
Flask with modular blueprints separating authentication, questionnaire delivery, and administration. Cosmos DB holds responses and user records; Blob Storage holds uploaded documents and serves them through time-limited signed links rather than public URLs. The summary generator runs against submitted responses as a distinct step, so it can be re-run without disturbing the underlying data.
Core Components
- • Flask web framework with modular blueprints
- • Azure Cosmos DB for scalable data persistence
- • Role-based authentication and authorisation
- • Section-based questionnaire engine
Azure & AI Integration
- • Azure Cosmos DB for document storage
- • Azure Blob Storage with time-limited access links
- • OpenAI for summary generation from responses
- • GitHub Actions CI/CD to Azure App Service
Application Workflow
1. Provisioning
Administrators create accounts with temporary credentials and assign each one to a tenant and role
2. Completion
Respondents work through a section-based questionnaire, with answers saved as they go rather than on final submit
3. Tracking
Section-level completion state rolls up into an administrator view of who is done, who is partway, and who has not started
4. Review and finalisation
Completed submissions enter a scheduled review round where reviewers comment and return them before anything is locked
5. Summary generation
Finalised responses feed the summary generator, producing a readable per-unit document from structured answers and free-text comments
Engineering notes
Partition key choice is the whole design
In Cosmos DB, partitioning by tenant keeps per-tenant queries to a single partition and makes cost scale with tenant count rather than total volume. Getting this wrong is expensive to undo later.
Review rounds are state, not a status field
Modelling the review period as a first-class entity with its own window and configuration made repeat cycles trivial. An earlier draft used a status flag on each response and could not represent a second round at all.
Save-as-you-go is a data-quality feature
Long questionnaires get abandoned. Persisting per-section rather than on final submit turned partial responses into usable data and removed the single most common support complaint.
Signed links over public blobs
Uploaded documents are never served from a public container. Access goes through short-lived signed URLs generated per request against the caller's role.
Related services
If you are collecting the same structured data from a lot of places and reconciling it by hand, these are the relevant places to start.