Fundamentals of Software Engineering

Chapter 11
Deployment, DevOps and Software Maintenance

Diploma in Software Engineering
Fundamentals of Software Engineering   •   Diploma

Deployment, DevOps and Software Maintenance

Introduction

Software engineering does not end when a program passes its tests. A software product creates value only when it can be released safely, operated reliably, monitored effectively, and changed economically throughout its useful life. Deployment is the controlled process of making software available in a target environment. DevOps is a set of practices, cultural principles, and technical capabilities that connect development and operations. Software maintenance is the disciplined modification of software after delivery to correct faults, adapt to change, improve quality, and prevent future problems.

These concerns are closely connected. Poor deployment practices increase operational incidents. Weak monitoring delays diagnosis. Uncontrolled maintenance creates technical debt and makes future releases risky. Conversely, automation, short feedback cycles, version control, and shared responsibility allow teams to deliver frequent changes without sacrificing reliability.

This chapter explains continuous integration and continuous delivery, deployment environments, containers, infrastructure automation, observability, incident response, maintenance types, and the evolution or retirement of legacy systems.

Learning Objectives

By the end of this chapter, you should be able to:

  • distinguish continuous integration, continuous delivery, and continuous deployment;
  • explain the purpose of development, testing, staging, and production environments;
  • describe containers and compare them with virtual machines;
  • explain infrastructure as code and configuration management;
  • distinguish monitoring, logging, tracing, and observability;
  • apply a basic incident-response process;
  • classify corrective, adaptive, perfective, and preventive maintenance;
  • evaluate strategies for evolving, replacing, or retiring legacy systems; and
  • identify professional, security, governance, and ethical responsibilities in deployment and maintenance.

1. From Code to a Running Service

A software change passes through a value stream: a developer modifies source code, the change is reviewed and built, automated tests are executed, a deployable artifact is produced, and the artifact is installed in an environment where users can access it. Each transition can introduce risk.

A deployment artifact is a versioned, immutable package such as a container image, library bundle, executable, or mobile application package. Building the same source code repeatedly should produce the same artifact, or at least a traceable artifact with documented differences. This principle is called reproducibility.

Deployment is broader than copying files. It may require database migrations, configuration, secrets, network rules, permissions, service registration, and rollback procedures. A release is the business or technical decision to make a particular version available; a deployment is the act of installing or activating it. A release may be deployed to production but kept invisible through a feature flag.

A useful deployment pipeline is:

Software delivery pipeline Sourceand review Buildartifact Automatedtests Deployprogressively Operateand learn Feedback: failures, usage, performance and business outcomes
Software delivery pipeline from source code to operation
Figure: Software delivery pipeline from source code to operation

Figure: A delivery pipeline with operational feedback returning to development.

2. DevOps and the Delivery Pipeline

DevOps is not simply a toolset or a job title. It combines collaboration, automation, measurement, and shared ownership between people who develop software and people who run it. The central idea is to reduce the distance between creating a change and learning whether that change works in real use.

Continuous integration

Continuous integration (CI) means that developers frequently merge small changes into a shared repository, after which an automated process builds the software and runs checks. A CI pipeline commonly includes compilation, unit tests, static analysis, dependency checks, security scanning, and artifact creation.

CI reduces integration risk because conflicts and defects are discovered close to the time they are introduced. It does not guarantee quality: inadequate tests, insecure dependencies, or poorly designed checks can still allow defects through. A healthy CI practice therefore uses fast feedback, protected branches, reproducible builds, and a clear policy for repairing a failing pipeline.

Continuous delivery and continuous deployment

Continuous delivery means that every change that passes the required pipeline is kept in a releasable state. A human or authorized business process may still decide when to release it. Continuous deployment goes further: qualifying changes are automatically released to production.

These terms should not be confused with continuous integration. Integration concerns merging and validating code; delivery concerns readiness for release; deployment concerns automatic production release. An organization can practice CI without continuous deployment, particularly where safety, regulation, or customer coordination requires explicit approval.

A delivery pipeline should include quality gates appropriate to risk. Examples include approval for a database migration, performance testing for a high-volume service, accessibility testing for a public interface, and verification that no secret is embedded in the artifact. Gates should be evidence-based rather than arbitrary bureaucracy.

Deployment strategies

Several strategies control release risk:

StrategyMain ideaStrengthLimitation
RecreateStop the old version and start the new oneSimpleDowntime and an abrupt change
RollingReplace instances graduallyUsually avoids full downtimeOld and new versions coexist
Blue-greenMaintain two environments and switch trafficFast rollbackRequires duplicate capacity
CanarySend a small user or traffic percentage to the new versionReal-user evidence at limited exposureRequires routing and monitoring
Feature flagDeploy code but activate functionality selectivelySeparates deployment from releaseInactive code and flag complexity

Rollback is not always safe. If a release changes a database schema irreversibly, returning to an older application may fail. Teams should prefer backward-compatible, expand-and-contract migrations: first add structures that both versions understand, migrate or dual-write data if necessary, then remove obsolete structures only after the old version is gone.

3. Deployment Environments and Configuration

An environment is a combination of compute resources, operating-system services, network policies, data stores, configuration, and external dependencies in which software runs. Common environments include:

  • Development: optimized for rapid local experimentation.
  • Integration or test: used for automated and exploratory testing against controlled dependencies.
  • Staging or pre-production: designed to resemble production closely enough to reveal deployment and configuration problems.
  • Production: serves real users and real business processes.
  • Disaster-recovery environment: prepared to restore service after major failure.

Environment parity means reducing irrelevant differences between environments. Perfect parity is often impractical, but differences should be deliberate, documented, and tested. For example, a developer may use a local database while staging uses a managed database service; the application’s connection interface should remain consistent.

Configuration includes values that vary by environment, such as service addresses, logging levels, capacity limits, and feature settings. Secrets include passwords, private keys, tokens, and certificates. Secrets must not be committed to source control or printed in logs. They should be held in an access-controlled secret manager, rotated, audited, and supplied to the application at runtime.

Configuration should be validated at startup. Failing clearly because a required database address is missing is safer than silently using a default production-like credential or an unintended endpoint. Access should follow least privilege: each service receives only the permissions required for its function.

4. Containers and Runtime Isolation

A container packages an application with its libraries and supporting files while sharing the host operating system kernel. It provides process and filesystem isolation, portability, rapid startup, and consistent packaging. A container is not necessarily a complete virtual machine and does not provide an independent kernel in the same way.

A virtual machine emulates or virtualizes hardware and runs a complete guest operating system. It generally provides stronger operating-system separation but consumes more resources and starts more slowly. Containers and virtual machines can also be combined: containers may run inside virtual machines in a cloud platform.

A container image should be treated as an immutable, versioned artifact. Good practice includes using a small trusted base image, pinning or controlling dependency versions, scanning for vulnerabilities, running as a non-root user, excluding build secrets, and rebuilding when the base image receives security updates. Images should be signed or otherwise associated with a trusted provenance record where the organizational risk justifies it.

Container orchestration manages scheduling, service discovery, health checks, scaling, secrets, and rolling updates across many containers. Orchestration does not eliminate engineering responsibility: a badly configured health check, excessive resource limit, or missing backup can still cause an outage.

5. Infrastructure Automation

Infrastructure as code (IaC) defines infrastructure in machine-readable files that can be reviewed, versioned, tested, and applied repeatedly. It may describe networks, servers, databases, identity permissions, load balancers, and monitoring resources. Configuration management applies desired operating-system or application settings to hosts.

The desired-state model can be expressed conceptually as:

Actual infrastructure + Applied changes → Desired infrastructure state

The arrow is not a numerical equation; it describes a control process. An IaC tool compares declared state with observed state and proposes actions. Safe practice includes code review, isolated plans, state locking, drift detection, policy checks, and controlled approvals for high-impact changes. State files may contain sensitive information and require access control and encryption.

Automation should be idempotent: applying the same declared configuration repeatedly should produce the same intended state rather than creating duplicate resources or accumulating unintended changes. Idempotence is a design goal, not a guarantee; external systems and time-dependent operations require special handling.

Automation improves repeatability, but it can also amplify mistakes. A faulty script can modify hundreds of servers quickly. Therefore, teams should use least privilege, small blast radiuses, dry runs, staged application, backups, and tested recovery procedures.

6. Observability and Service Reliability

Monitoring asks whether known conditions are within acceptable limits. Observability is the broader ability to infer the internal state of a system from its externally visible outputs. The principal telemetry types are:

  • Metrics: numeric time-series measurements, such as request rate, error rate, latency, memory use, and queue depth.
  • Logs: timestamped records of events, ideally structured and correlated with a request or user action.
  • Traces: records of a request’s path across services, showing spans, timing, and dependencies.
  • Profiles and events: information about resource consumption or significant state changes.

The four commonly used service-level indicators are availability, latency, throughput, and correctness. A service-level objective (SLO) states a target, such as a percentage of successful requests during a defined period. A service-level agreement (SLA) is a commitment, often contractual, that may include consequences if targets are missed.

If an SLO requires 99.9% successful availability over a 30-day month, the permitted unavailability is approximately 0.1% of the period. Using a 30-day approximation:

30 × 24 × 60 × 0.001 = 43.2 minutes

This calculation assumes that the SLO measures the whole 30-day period uniformly and that “unavailable” is defined consistently. It does not establish the organization’s legal SLA or account for exclusions. The resulting error budget is the amount of unreliability the team can spend while remaining within the objective. A team that has exhausted its error budget may sensibly postpone risky feature work and prioritize reliability.

Alerts should be actionable, urgent enough to matter, and resistant to noise. Alerting on every log message produces fatigue. A good alert identifies a user-impacting symptom, includes context, and links to a response procedure. Dashboards support investigation but should not replace alerts.

7. Incident Response

An incident is an unplanned event that reduces or threatens the availability, confidentiality, integrity, performance, or safety of a service. Incident response is a coordinated process, not an improvised search for someone to blame.

A practical response sequence is:

  1. Detect and assess: confirm the signal, estimate user and business impact, and assign severity.
  2. Declare and coordinate: create an incident record, appoint an incident lead, and establish a communication channel.
  3. Contain: reduce harm through rollback, traffic limitation, isolation, failover, or disabling a feature.
  4. Diagnose: use recent changes, telemetry, dependency status, and controlled tests to identify likely causes.
  5. Recover: restore acceptable service and verify that the recovery is real.
  6. Communicate: provide accurate, timely information to users, managers, suppliers, and regulators where required.
  7. Learn: conduct a blameless review, identify contributing factors, and track corrective actions.

Severity should reflect impact and urgency, not the seniority of the person reporting the problem. During response, teams should preserve evidence, protect personal data, record decisions, and avoid destructive experimentation in production. A post-incident review should examine system conditions, process weaknesses, and organizational incentives. “Human error” may be a contributing action, but it is rarely a sufficient root explanation; resilient systems make dangerous errors difficult to perform and easy to detect.

8. Software Maintenance

Maintenance begins after software is delivered, although maintainability should be designed from the start. Four traditional categories are useful:

TypePurposeExample
CorrectiveRemove discovered faultsFix incorrect tax calculation
AdaptiveRespond to changed environmentsSupport a new operating-system API
PerfectiveImprove functionality, performance, or usabilitySimplify a slow search workflow
PreventiveReduce future failure or maintenance costRefactor duplicated validation code

The categories can overlap. Replacing an insecure library is adaptive because the external dependency changed, corrective because it removes a vulnerability, and preventive because it reduces future exposure. Classification is useful for planning, reporting, and budgeting, not for forcing every change into one exclusive label.

Maintenance cost is influenced by architecture, code readability, test coverage, documentation, dependency health, team knowledge, and operational complexity. Technical debt is not simply “bad code”; it is the future cost or constraint created when a design shortcut is taken. Debt can be deliberate and rational when managed, but hidden and compounding debt increases change risk.

A maintenance request should be evaluated for purpose, risk, affected components, dependencies, test strategy, security impact, rollback, and documentation. Change control should be proportional: a small low-risk correction need not face the same approval process as a change to identity, payment, safety, or regulated data.

9. Legacy-System Evolution and Retirement

A legacy system is an existing system whose technology, architecture, documentation, or operating assumptions make change difficult, regardless of whether it still delivers essential value. Legacy status is contextual: a stable older system may be strategically useful, while a modern system with poor ownership may be difficult to maintain.

Before changing a legacy system, teams should discover its real behavior. Useful activities include dependency mapping, data-flow analysis, log review, interviews with users and operators, characterization tests, and measurement of failure modes. Characterization tests record what the system currently does, including awkward behavior, so that an improvement does not unintentionally break an essential dependency.

Common evolution strategies include:

  • Encapsulation: place a stable interface around the old system.
  • Strangler approach: gradually route selected capabilities to new components while the old system remains temporarily active.
  • Refactoring: improve internal structure without changing externally visible behavior.
  • Replacement: build and migrate to a new system.
  • Replatforming: move to a new runtime or infrastructure with limited functional change.
  • Retirement: stop operation after data, legal, contractual, and user obligations are addressed.

Replacement is not automatically superior. A new system may reproduce old defects, lose undocumented business rules, or create migration risk. A strangler approach reduces the size of each change but can produce a complicated period of dual systems. Parallel operation requires reconciliation rules, ownership of conflicting records, and a clear end date.

Retirement requires more than switching off a server. The organization should identify users and integrations, archive or dispose of data according to retention and privacy requirements, revoke credentials, terminate infrastructure, update documentation, preserve audit evidence, and communicate the change. Secure disposal must prevent unauthorized recovery of sensitive information.

10. Governance, Ethics, Security, and Contemporary Practice

Deployment pipelines have significant power. They can expose personal data, change financial records, or deny access to essential services. Governance therefore includes separation of duties where justified, traceable approvals, audit logs, access reviews, segregation of production credentials, vulnerability management, backup verification, and compliance with applicable privacy, accessibility, safety, and sector regulations.

Automation and AI-assisted development can generate code, tests, configuration, and incident summaries. These tools may improve productivity, but generated output is not automatically correct, secure, licensed appropriately, or suitable for a particular context. Teams must review generated code, avoid exposing confidential data to unauthorized services, verify dependency provenance, and retain human accountability for production decisions. AI-generated tests can repeat the same assumptions as the code under test; independent test design remains important.

Contemporary delivery practices increasingly emphasize software supply-chain security. Organizations track dependencies, scan images, protect build systems, sign artifacts, and maintain provenance records. They also apply progressive delivery, policy as code, ephemeral test environments, and cost-aware operations. These techniques should be selected according to risk and organizational capability rather than adopted as fashionable labels.

Applied Case: Northstar College Registration Service

Background

Northstar College operates an online registration service used by students, staff, and finance systems. The service was deployed manually several times each semester. Releases were infrequent, configuration differed between testing and production, and operators discovered failures through student complaints.

Problem

A new release introduced a database query that performed acceptably with test data but became very slow during registration week. The service remained technically online, yet students experienced timeouts. Logs were inconsistent, there was no request tracing, and the team could not quickly determine whether the application or database was responsible.

Analysis

The college mapped the delivery process and found several risks: no reproducible artifact, shared production credentials, manual database changes, weak load testing, and no agreed service objective. The team also discovered that an old reporting system depended on an undocumented database table.

Approach and solution

The team first introduced source-controlled builds and CI with unit, integration, and migration tests. It created a staging environment using production-like database characteristics without copying personal data. Configuration and secrets were separated from the application artifact and stored with controlled access.

The service was packaged as a container and deployed using a rolling strategy. Infrastructure definitions were placed under version control. Structured logs, request identifiers, database timing metrics, and distributed traces were added. The team defined an objective for successful registration requests and created an alert based on user-visible failure rate rather than raw CPU usage.

Before the next registration period, the college used load tests based on expected peak traffic. A canary release sent a small proportion of requests to the new version. The database query was indexed and rewritten, while a backward-compatible migration preserved the reporting system’s interface. An incident runbook documented rollback, communication, and escalation.

Outcome

The next release was delivered in smaller increments. During a later performance degradation, the alert identified the affected endpoint within minutes, and the team reduced traffic to the problematic feature while investigating. The college did not eliminate all incidents, but it reduced detection time, improved recovery, and gained evidence for future capacity decisions.

Learning points

The case demonstrates that DevOps is a socio-technical improvement rather than a container purchase. Automation helped only after the team clarified ownership and testing. Observability connected technical signals to user impact. Backward compatibility protected an undocumented dependency. Finally, reliability required both engineering controls and operational rehearsal.

Challenges and Limitations

DevOps practices can fail when organizations optimize deployment frequency while ignoring reliability, security, accessibility, or user value. Excessive automation can make a pipeline difficult to understand. Excessive manual approval can create queues and encourage unsafe workarounds. Metrics can be gamed: a high number of deployments does not prove good engineering, and a low incident count may indicate under-reporting.

Containers can create false confidence about security; isolation is not absolute, and vulnerable images remain vulnerable. IaC can encode insecure permissions at scale. Observability can become expensive and can collect personal data unnecessarily. Logging user identifiers or request payloads may violate privacy principles. Teams should minimize collected data, restrict access, define retention periods, and redact secrets.

Maintenance also involves difficult trade-offs. A rewrite may be attractive to developers but unaffordable or risky for the business. Continuing a legacy system may preserve stability but increase skills scarcity and security exposure. Decisions should be based on evidence about value, risk, total cost, and the ability to recover from failure.

Best-Practice Checklist

  • Keep source, configuration definitions, infrastructure definitions, and runbooks under appropriate version control.
  • Build once and promote the same tested artifact through environments.
  • Automate fast, meaningful tests and repair failing pipelines promptly.
  • Store secrets separately, apply least privilege, and rotate credentials.
  • Use backward-compatible migrations and rehearse rollback and recovery.
  • Monitor user-visible service indicators, not only infrastructure utilization.
  • Make alerts actionable and conduct blameless post-incident reviews.
  • Classify maintenance work and reserve capacity for preventive improvement.
  • Map dependencies before evolving or retiring a legacy system.
  • Protect privacy, accessibility, security, auditability, and human accountability.

Chapter Summary

Deployment makes a tested software artifact available in a target environment, while release management controls when users receive its functionality. Continuous integration validates frequent changes; continuous delivery keeps changes releasable; continuous deployment automates production release when organizational risk permits. Environments should be sufficiently similar to expose defects while keeping data and access controlled.

Containers package applications consistently but do not replace security or operational discipline. Infrastructure as code makes infrastructure repeatable and reviewable, provided that state, permissions, drift, and blast radius are controlled. Observability combines metrics, logs, traces, and other evidence to explain system behavior. Incident response emphasizes assessment, coordination, containment, recovery, communication, and learning.

Corrective, adaptive, perfective, and preventive maintenance describe different reasons for changing software. Legacy systems should be understood before they are modified, and evolution, replacement, or retirement should be selected according to value and risk. Across all these activities, reliable software engineering depends on automation balanced with human judgment, governance, security, privacy, and responsibility to users.

Key Terms

Deployment: The process of installing or activating software in a target environment.

Release: A decision or event that makes a software version available to users.

Continuous integration: Frequent merging of code followed by automated build and validation.

Continuous delivery: Keeping every validated change in a releasable state.

Continuous deployment: Automatically releasing qualifying changes to production.

Artifact: A versioned, deployable output produced by a build.

Environment: The resources, configuration, dependencies, and controls in which software runs.

Container: An isolated process package that shares the host operating-system kernel.

Infrastructure as code: Machine-readable, versioned definitions of infrastructure.

Idempotence: The property that repeating an operation produces the same intended state.

Observability: The ability to infer internal system state from external outputs.

Metric: A numeric measurement collected over time.

Trace: A record of a request’s path through system components.

Service-level objective: A target for a measured service property.

Error budget: The permitted unreliability implied by a service-level objective.

Incident: An unplanned event that harms or threatens service quality or security.

Corrective maintenance: Maintenance that removes discovered faults.

Adaptive maintenance: Maintenance responding to changed environments or dependencies.

Technical debt: Future cost or constraint created by a shortcut or deferred improvement.

Legacy system: An existing system whose technology, knowledge, or dependencies make change difficult.

Review Questions

Short Answer Questions

  1. What is the difference between continuous delivery and continuous deployment?
  2. Why should secrets be separated from application artifacts?
  3. State two differences between a container and a virtual machine.
  4. What are the four traditional categories of software maintenance?
  5. Why are backward-compatible database migrations useful?

Long Answer Questions

  1. Explain how a CI/CD pipeline can reduce deployment risk, and identify situations in which human approval remains appropriate.
  2. Compare rolling, blue-green, and canary deployment strategies, including one advantage and one limitation of each.
  3. Explain observability using metrics, logs, and traces, and show how these forms of evidence support incident response.
  4. Discuss the relationship between infrastructure as code, idempotence, drift detection, and access control.
  5. Describe a systematic process for evaluating whether a legacy system should be evolved, replaced, or retired.

Analytical / Application Questions

  1. A service has frequent deployments but rising incidents and poor user satisfaction. Analyze which DevOps practices or measures may be misleading, and propose a balanced improvement plan.
  2. Design an incident-response approach for a registration system that is slow but not completely unavailable. Specify detection, coordination, containment, recovery, communication, and follow-up actions.
  3. A legacy payroll system shares a database with reporting and compliance applications. Recommend an evolution strategy and identify migration, data, security, and retirement risks.

Multiple Choice Questions with Answers

Question 1

Which statement best describes continuous integration?

A. Automatically releasing every change directly to production

B. Frequently merging changes and automatically building and testing them

C. Manually copying source files to a staging server

D. Replacing all virtual machines with containers

Correct Answer: B. Frequently merging changes and automatically building and testing them

Question 2

Which deployment strategy sends a small proportion of real traffic to a new version first?

A. Recreate deployment

B. Blue-green deployment

C. Canary deployment

D. Offline deployment

Correct Answer: C. Canary deployment

Question 3

Why should a deployment pipeline build once and promote the same artifact?

A. To ensure tested code is the code that is released

B. To avoid using version control

C. To make production configuration identical to developer laptops

D. To eliminate the need for testing

Correct Answer: A. To ensure tested code is the code that is released

Question 4

Which statement about containers is correct?

A. Every container runs a complete independent guest kernel

B. Containers normally share the host operating-system kernel

C. Containers cannot be versioned as images

D. Containers automatically guarantee application security

Correct Answer: B. Containers normally share the host operating-system kernel

Question 5

What is the main purpose of infrastructure as code?

A. To replace all application source code

B. To define and manage infrastructure in reviewable, repeatable files

C. To store passwords in public repositories

D. To prevent infrastructure monitoring

Correct Answer: B. To define and manage infrastructure in reviewable, repeatable files

Question 6

Which telemetry type records the path of a request across multiple services?

A. Trace

B. Metric

C. Static-analysis report

D. Feature flag

Correct Answer: A. Trace

Question 7

An availability objective is 99.9% over a 30-day period. Approximately how much unavailability does this permit?

A. 4.32 minutes

B. 14.4 minutes

C. 43.2 minutes

D. 432 minutes

Correct Answer: C. 43.2 minutes

Question 8

Replacing an API because its external provider changed is primarily which maintenance type?

A. Adaptive maintenance

B. Corrective maintenance

C. Preventive maintenance only

D. No maintenance

Correct Answer: A. Adaptive maintenance

Question 9

Which action is most appropriate during the containment phase of an incident?

A. Publish an unverified explanation

B. Reduce harm by rolling back or disabling an affected feature

C. Delete all logs immediately

D. Wait until the root cause is proven before taking any action

Correct Answer: B. Reduce harm by rolling back or disabling an affected feature

Question 10

What is a major purpose of characterization tests in legacy-system work?

A. To document current externally visible behavior before changing it

B. To guarantee that a replacement has no defects

C. To remove all undocumented dependencies automatically

D. To measure only developer productivity

Correct Answer: A. To document current externally visible behavior before changing it

Fundamentals of Software Engineering
Chapter 11 of 15