Environments and Software Development Lifecycle
Before you start
You need: requirements and stories (Article 02) and the application layers (Article 03).
Time: about 40 minutes, plus the practice.
Learning objective
Follow one School Management System feature through every lifecycle stage and every environment, and explain what changes between them.
Topics
- The lifecycle stages
- Waterfall and Agile
- Sprints
- The environment model
- What moves between environments, and what does not
- Configuration and secrets
- The work-item flow
- Traceability
The lifecycle stages
| Stage | Produces | Who leads |
|---|---|---|
| Requirements | User stories with acceptance criteria | BA, Product Owner |
| Design | Screen designs, data model, technical approach | Lead, Architect, Designer |
| Development | Working, reviewed code | Developers |
| Testing | Verified behaviour, defect reports | QA |
| Deployment | The software running in an environment | DevOps |
| Maintenance | Fixes, small changes, support | Everyone |
These are stages, not a strict order. In Agile, a two-week sprint runs all six for a small slice of work.
Maintenance is the longest stage by far. NexCoding Academy's portal was built in four months and has been maintained for three years. Most of your career is spent here, which is why Track 04 exists and why reading code matters more than writing it.
Waterfall and Agile
| Waterfall | Agile | |
|---|---|---|
| Order | Each stage completes before the next | All stages, repeatedly, on small slices |
| Delivery | Once, at the end | Every sprint |
| Requirements | Fixed up front | Refined continuously |
| Feedback | After release | Every two weeks |
| Suits | Fixed regulatory scope | Most business software |
Waterfall's flaw is that everything is agreed before anyone has seen anything. The school signs off a specification in January and first sees the software in September, by which time the fee structure has changed.
Agile's flaw is that "we'll refine it later" can mean nothing is ever decided. Both fail when practised without discipline.
Most teams run something in between: fixed architecture and scope for a release, iterative delivery within it.
Sprints
A sprint is a fixed period — almost always two weeks — during which the team commits to a set of stories.
Sprint 14 (Monday 4 August → Friday 15 August)
Day 1 Sprint planning — pick stories, estimate, commit
Days 1-9 Development, review, QA; daily stand-up each morning
Day 8 Backlog grooming for Sprint 15
Day 10 Sprint review (demo) and retrospective
| Event | Purpose |
|---|---|
| Planning | Decide what the team commits to |
| Stand-up | 15 minutes daily; synchronise and surface blockers |
| Grooming | Clarify upcoming stories before they are planned |
| Review / demo | Show finished work to the people who asked for it |
| Retrospective | What went well, what did not, what changes |
The commitment is to the sprint's stories, not to hours. A story estimated at 3 points that turns out to be 8 is information, raised in stand-up — not something to absorb silently by working late.
Unfinished work returns to the backlog. It is not "carried over" quietly; it is re-estimated and re-prioritised, because a story that took longer than expected may no longer be the most valuable next thing.
A story is only demonstrated if it meets the Definition of Done. Half-finished work is not shown, because showing it creates an expectation that it exists.
The environment model
An environment is a complete running copy of the system — application, database, configuration.
Development → QA / Testing → UAT / Staging → Production
| Environment | Who uses it | Data | Deploys |
|---|---|---|---|
| Development | Developers | Fake, ~20 students | Constantly |
| QA / Testing | QA engineers | Test data covering edge cases | Every merge |
| UAT / Staging | The school's own staff | A copy of production, anonymised | Once per sprint |
| Production | Real users | Real student records | On release |
UAT means User Acceptance Testing. It is where the principal and office staff try the software and say whether it does what they asked. It is the last gate before real users, and it catches a different class of problem from QA — not "does this work" but "is this what we meant".
Development has 20 students; production has 800. That gap explains a large share of "it works on my machine":
| Difference | What it hides |
|---|---|
| Data volume | A query fine on 20 rows takes 40 seconds on 800 |
| Data variety | Nobody in development is absent, has two fee accounts, or has an apostrophe in their name |
| Concurrency | One developer clicks once; 30 staff click at the same moment |
| Configuration | Different connection strings, URLs, timeouts |
| Permissions | Your login is an admin; the application's is not |
UAT exists to close that gap — same data shape as production, real users, before it matters.
What moves, and what does not
| Moves between environments | Stays per environment |
|---|---|
| Compiled application code | Connection strings |
| Database schema changes (migrations) | API URLs |
| Static assets | Passwords, API keys, tokens |
| Configuration structure | Logging levels |
| Feature flags | |
| The data itself |
Code moves. Configuration does not. The same build is deployed to QA, UAT and production; what differs is the settings it reads at startup.
// appsettings.json — structure, committed
{
"ConnectionStrings": { "SchoolDb": "" },
"Jwt": { "Issuer": "", "Audience": "" },
"Logging": { "LogLevel": { "Default": "Information" } }
}
The keys are committed. The values are not.
Building separately for each environment is a mistake, because then the thing tested in QA is not the thing shipped. One build, promoted through environments, is the rule.
Never copy production data into development. It contains real children's names, dates of birth and parents' phone numbers. If realistic data is needed, anonymise it first — replace names with the standard examples, phone numbers with placeholders. Track 18 covers this again, because it is also a rule about what you paste into an AI tool.
Configuration and secrets
| Where | For |
|---|---|
appsettings.json | Non-secret defaults; committed |
appsettings.Development.json | Local overrides; not committed |
| User secrets | Local secrets, stored outside the repository |
| Environment variables | Server configuration |
| A secrets vault | Production credentials |
A committed secret is a leaked secret. Deleting it in a later commit does not remove it from history — the only real fix is rotating the credential. Track 16 shows exactly why.
Wrong: "SchoolDb": "Server=prod-sql-01;User Id=sa;Password=P@ssw0rd123;"
Right: "SchoolDb": "" (value supplied per environment)
A /version endpoint answers "what is actually deployed?" without archaeology:
{ "version": "2.4.1", "commit": "a3f9c1d", "environment": "Production" }
The work-item flow
Backlog
│ prioritised, not yet planned
▼
Ready
│ criteria clear, estimated, nothing blocking
▼
In Progress
│ a developer is working on it, on a branch
▼
In Review
│ pull request open; a colleague is reading it
▼
In QA
│ merged and deployed to QA; being verified
▼
Ready for UAT
│ QA passed; awaiting the sprint's UAT session
▼
Done
accepted, in the release
Move your own items yourself, on the day. A board that is out of date is worse than no board — stand-up is spent reconstructing reality instead of using it.
Items can move backwards. QA finding a defect returns the item to In Progress. That is the process working, not a failure; the point of QA is to find things.
Traceability
Every change should be traceable from a business request to the line of code and the release it shipped in.
Business request Office staff spend ten minutes finding one student
│
Work item NCA-142 "Search students by roll number"
│
Branch feature/142-student-search
│
Commits "Add student search query to StudentRepository"
│
Pull request #87, reviewed by Priya Sharma, references #142
│
Build CI run 431, all tests passing
│
Release v2.4.0, deployed 15 August 2026
│
Verification UAT sign-off by the office administrator
Put the item number in the branch name and the commit message. Eighteen months later someone will ask why a line exists, and this chain is the only answer.
It also answers the questions that arrive under pressure: what is in this release, when did this ship, who approved it, and what was it meant to fix.
Where this goes wrong
| The mistake | Consequence |
|---|---|
| Testing only on development data | 20 clean rows hide what 800 real ones do |
| Rebuilding for each environment | The thing tested is not the thing shipped |
| Committing a connection string | A leaked credential that stays in history forever |
| Copying production data to development | Real children's names and phone numbers on a laptop |
| Not updating the board | Stand-up spent reconstructing reality |
| Skipping UAT because the sprint is late | The people who asked for it see it first in production |
| No version endpoint | Nobody can say what is actually deployed |
"It works on my machine" is a statement about the difference between two environments, and that difference is where the bug lives.
Common mistakes
- Testing only on development data
- Building separately per environment
- Committing a connection string or an API key
- Copying production data into development
- Not updating the board
- Treating a QA rejection as a personal failure
- Skipping UAT because the sprint is late
- No version endpoint, so nobody knows what is deployed
- Branch names and commits with no work-item reference
- Deploying on a Friday afternoon
Practice
- List the six lifecycle stages and name what each produces.
- Write out a two-week sprint calendar with all five events.
- Take one story and describe what happens to it in each of the four environments.
- List five differences between your development database and a production one with 800 students.
- For each difference, name a bug it could hide.
- Explain what UAT catches that QA does not.
- Write an
appsettings.jsonwith keys and empty values, and list where each value would come from per environment. - Find a real repository and check whether any secret was ever committed.
- Design a
/versionendpoint response and say what each field answers. - Draw the work-item flow and mark every point where an item can move backwards.
- Trace one change you have made through the full traceability chain. Note which links are missing.
- Write a branch name and a commit message that reference a work item.
- Explain why one build promoted through environments is safer than four separate builds.
Exercises 4 and 5 are the pair that explains "it works on my machine" permanently.
You can now
- Name the six lifecycle stages and what each produces
- Describe what happens in each of the four environments
- Say what moves between environments and what does not
- Explain why UAT catches things QA cannot
- Trace a change from business request to release
- Say why production data must never reach a developer machine
Review questions
- What is a sprint, and what happens to work that is unfinished at the end of one?
- Why is the same build promoted through environments rather than rebuilt for each?
- What does UAT catch that QA does not?
- Why must production data never be copied into development?
Next: Testing and quality