Skip to main content
Published / updated

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

StageProducesWho leads
RequirementsUser stories with acceptance criteriaBA, Product Owner
DesignScreen designs, data model, technical approachLead, Architect, Designer
DevelopmentWorking, reviewed codeDevelopers
TestingVerified behaviour, defect reportsQA
DeploymentThe software running in an environmentDevOps
MaintenanceFixes, small changes, supportEveryone

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

WaterfallAgile
OrderEach stage completes before the nextAll stages, repeatedly, on small slices
DeliveryOnce, at the endEvery sprint
RequirementsFixed up frontRefined continuously
FeedbackAfter releaseEvery two weeks
SuitsFixed regulatory scopeMost 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
EventPurpose
PlanningDecide what the team commits to
Stand-up15 minutes daily; synchronise and surface blockers
GroomingClarify upcoming stories before they are planned
Review / demoShow finished work to the people who asked for it
RetrospectiveWhat 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
EnvironmentWho uses itDataDeploys
DevelopmentDevelopersFake, ~20 studentsConstantly
QA / TestingQA engineersTest data covering edge casesEvery merge
UAT / StagingThe school's own staffA copy of production, anonymisedOnce per sprint
ProductionReal usersReal student recordsOn 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":

DifferenceWhat it hides
Data volumeA query fine on 20 rows takes 40 seconds on 800
Data varietyNobody in development is absent, has two fee accounts, or has an apostrophe in their name
ConcurrencyOne developer clicks once; 30 staff click at the same moment
ConfigurationDifferent connection strings, URLs, timeouts
PermissionsYour 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 environmentsStays per environment
Compiled application codeConnection strings
Database schema changes (migrations)API URLs
Static assetsPasswords, API keys, tokens
Configuration structureLogging 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

WhereFor
appsettings.jsonNon-secret defaults; committed
appsettings.Development.jsonLocal overrides; not committed
User secretsLocal secrets, stored outside the repository
Environment variablesServer configuration
A secrets vaultProduction 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 mistakeConsequence
Testing only on development data20 clean rows hide what 800 real ones do
Rebuilding for each environmentThe thing tested is not the thing shipped
Committing a connection stringA leaked credential that stays in history forever
Copying production data to developmentReal children's names and phone numbers on a laptop
Not updating the boardStand-up spent reconstructing reality
Skipping UAT because the sprint is lateThe people who asked for it see it first in production
No version endpointNobody 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

  1. List the six lifecycle stages and name what each produces.
  2. Write out a two-week sprint calendar with all five events.
  3. Take one story and describe what happens to it in each of the four environments.
  4. List five differences between your development database and a production one with 800 students.
  5. For each difference, name a bug it could hide.
  6. Explain what UAT catches that QA does not.
  7. Write an appsettings.json with keys and empty values, and list where each value would come from per environment.
  8. Find a real repository and check whether any secret was ever committed.
  9. Design a /version endpoint response and say what each field answers.
  10. Draw the work-item flow and mark every point where an item can move backwards.
  11. Trace one change you have made through the full traceability chain. Note which links are missing.
  12. Write a branch name and a commit message that reference a work item.
  13. 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

  1. What is a sprint, and what happens to work that is unfinished at the end of one?
  2. Why is the same build promoted through environments rather than rebuilt for each?
  3. What does UAT catch that QA does not?
  4. Why must production data never be copied into development?

Next: Testing and quality