Files
nexus/sreweekly/articles/169/05-minimising-the-risk-of-data-damage.html
2026-09-12 17:23:01 +08:00

521 lines
44 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<!--[if IEMobile 7 ]> <html lang="en-US"class="no-js iem7"> <![endif]-->
<!--[if lt IE 7 ]> <html lang="en-US" class="no-js ie6"> <![endif]-->
<!--[if IE 7 ]> <html lang="en-US" class="no-js ie7"> <![endif]-->
<!--[if IE 8 ]> <html lang="en-US" class="no-js ie8"> <![endif]-->
<!--[if (gte IE 9)|(gt IEMobile 7)|!(IEMobile)|!(IE)]><!--><html lang="en-US" class="no-js"><!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>
Minimising the Risk of Data Damage </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- icons & favicons -->
<!-- For iPhone 4 -->
<!-- For everything else -->
<link rel="shortcut icon" href="/favicon.ico">
<link rel="me" href="https://twitter.com/benjiweber">
<!-- media-queries.js (fallback) -->
<!--[if lt IE 9]>
<script src="http://css3-mediaqueries-js.googlecode.com/svn/trunk/css3-mediaqueries.js"></script>
<![endif]-->
<!-- html5.js -->
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link rel="pingback" href="https://benjiweber.co.uk/blog/xmlrpc.php">
<link rel="stylesheet/less" type="text/css" href="https://benjiweber.co.uk/blog/wp-content/themes/wordpress-bootstrap/less/bootstrap.less">
<link rel="stylesheet/less" type="text/css" href="https://benjiweber.co.uk/blog/wp-content/themes/wordpress-bootstrap/less/responsive.less">
<link rel="alternate" type="application/rss+xml" href="http://benjiweber.co.uk/blog/feed/" title="Benji Weber's Blog - RSS"/>
<!-- wordpress head functions -->
<meta name='robots' content='max-image-preview:large' />
<!-- This site is optimized with the Yoast SEO plugin v14.9 - https://yoast.com/wordpress/plugins/seo/ -->
<meta name="robots" content="index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1" />
<link rel="canonical" href="https://benjiweber.co.uk/blog/2015/03/21/minimising-the-risk-of-data-damage/" />
<meta property="og:locale" content="en_US" />
<meta property="og:type" content="article" />
<meta property="og:title" content="Minimising the Risk of Data Damage - Benji&#039;s Blog" />
<meta property="og:description" content="One of the more interesting questions that came up at Pipeline Conference was: &#8220;How can we mitigate the risk of releasing a change that damages our data?&#8221; When we have a database holding data that may be updated and deleted, as well as inserted/queried, then there’s a risk of releasing a change that causes the... Read more &raquo;" />
<meta property="og:url" content="https://benjiweber.co.uk/blog/2015/03/21/minimising-the-risk-of-data-damage/" />
<meta property="og:site_name" content="Benji&#039;s Blog" />
<meta property="article:published_time" content="2015-03-21T18:41:37+00:00" />
<meta property="article:modified_time" content="2019-01-04T10:45:24+00:00" />
<meta property="og:image" content="http://benjiweber.co.uk/datarisk-groupbyimportance.png" />
<meta name="twitter:card" content="summary_large_image" />
<script type="application/ld+json" class="yoast-schema-graph">{"@context":"https://schema.org","@graph":[{"@type":"WebSite","@id":"https://benjiweber.co.uk/blog/#website","url":"https://benjiweber.co.uk/blog/","name":"Benji&#039;s Blog","description":"","potentialAction":[{"@type":"SearchAction","target":"https://benjiweber.co.uk/blog/?s={search_term_string}","query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"ImageObject","@id":"https://benjiweber.co.uk/blog/2015/03/21/minimising-the-risk-of-data-damage/#primaryimage","inLanguage":"en-US","url":"http://benjiweber.co.uk/datarisk-groupbyimportance.png"},{"@type":"WebPage","@id":"https://benjiweber.co.uk/blog/2015/03/21/minimising-the-risk-of-data-damage/#webpage","url":"https://benjiweber.co.uk/blog/2015/03/21/minimising-the-risk-of-data-damage/","name":"Minimising the Risk of Data Damage - Benji&#039;s Blog","isPartOf":{"@id":"https://benjiweber.co.uk/blog/#website"},"primaryImageOfPage":{"@id":"https://benjiweber.co.uk/blog/2015/03/21/minimising-the-risk-of-data-damage/#primaryimage"},"datePublished":"2015-03-21T18:41:37+00:00","dateModified":"2019-01-04T10:45:24+00:00","author":{"@id":"https://benjiweber.co.uk/blog/#/schema/person/45ecb36b51f4ce99e6929d2d31ca5c09"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https://benjiweber.co.uk/blog/2015/03/21/minimising-the-risk-of-data-damage/"]}]},{"@type":"Person","@id":"https://benjiweber.co.uk/blog/#/schema/person/45ecb36b51f4ce99e6929d2d31ca5c09","name":"benji","image":{"@type":"ImageObject","@id":"https://benjiweber.co.uk/blog/#personlogo","inLanguage":"en-US","url":"https://secure.gravatar.com/avatar/05fb47b31a0b329e1b790074a9b624ef?s=96&d=mm&r=g","caption":"benji"}}]}</script>
<!-- / Yoast SEO plugin. -->
<link rel='dns-prefetch' href='//s.w.org' />
<script type="text/javascript">
window._wpemojiSettings = {"baseUrl":"https:\/\/s.w.org\/images\/core\/emoji\/14.0.0\/72x72\/","ext":".png","svgUrl":"https:\/\/s.w.org\/images\/core\/emoji\/14.0.0\/svg\/","svgExt":".svg","source":{"concatemoji":"https:\/\/benjiweber.co.uk\/blog\/wp-includes\/js\/wp-emoji-release.min.js?ver=6.0.5"}};
/*! This file is auto-generated */
!function(e,a,t){var n,r,o,i=a.createElement("canvas"),p=i.getContext&&i.getContext("2d");function s(e,t){var a=String.fromCharCode,e=(p.clearRect(0,0,i.width,i.height),p.fillText(a.apply(this,e),0,0),i.toDataURL());return p.clearRect(0,0,i.width,i.height),p.fillText(a.apply(this,t),0,0),e===i.toDataURL()}function c(e){var t=a.createElement("script");t.src=e,t.defer=t.type="text/javascript",a.getElementsByTagName("head")[0].appendChild(t)}for(o=Array("flag","emoji"),t.supports={everything:!0,everythingExceptFlag:!0},r=0;r<o.length;r++)t.supports[o[r]]=function(e){if(!p||!p.fillText)return!1;switch(p.textBaseline="top",p.font="600 32px Arial",e){case"flag":return s([127987,65039,8205,9895,65039],[127987,65039,8203,9895,65039])?!1:!s([55356,56826,55356,56819],[55356,56826,8203,55356,56819])&&!s([55356,57332,56128,56423,56128,56418,56128,56421,56128,56430,56128,56423,56128,56447],[55356,57332,8203,56128,56423,8203,56128,56418,8203,56128,56421,8203,56128,56430,8203,56128,56423,8203,56128,56447]);case"emoji":return!s([129777,127995,8205,129778,127999],[129777,127995,8203,129778,127999])}return!1}(o[r]),t.supports.everything=t.supports.everything&&t.supports[o[r]],"flag"!==o[r]&&(t.supports.everythingExceptFlag=t.supports.everythingExceptFlag&&t.supports[o[r]]);t.supports.everythingExceptFlag=t.supports.everythingExceptFlag&&!t.supports.flag,t.DOMReady=!1,t.readyCallback=function(){t.DOMReady=!0},t.supports.everything||(n=function(){t.readyCallback()},a.addEventListener?(a.addEventListener("DOMContentLoaded",n,!1),e.addEventListener("load",n,!1)):(e.attachEvent("onload",n),a.attachEvent("onreadystatechange",function(){"complete"===a.readyState&&t.readyCallback()})),(e=t.source||{}).concatemoji?c(e.concatemoji):e.wpemoji&&e.twemoji&&(c(e.twemoji),c(e.wpemoji)))}(window,document,window._wpemojiSettings);
</script>
<style type="text/css">
img.wp-smiley,
img.emoji {
display: inline !important;
border: none !important;
box-shadow: none !important;
height: 1em !important;
width: 1em !important;
margin: 0 0.07em !important;
vertical-align: -0.1em !important;
background: none !important;
padding: 0 !important;
}
</style>
<link rel='stylesheet' id='wp-block-library-css' href='https://benjiweber.co.uk/blog/wp-includes/css/dist/block-library/style.min.css?ver=6.0.5' type='text/css' media='all' />
<style id='global-styles-inline-css' type='text/css'>
body{--wp--preset--color--black: #000000;--wp--preset--color--cyan-bluish-gray: #abb8c3;--wp--preset--color--white: #ffffff;--wp--preset--color--pale-pink: #f78da7;--wp--preset--color--vivid-red: #cf2e2e;--wp--preset--color--luminous-vivid-orange: #ff6900;--wp--preset--color--luminous-vivid-amber: #fcb900;--wp--preset--color--light-green-cyan: #7bdcb5;--wp--preset--color--vivid-green-cyan: #00d084;--wp--preset--color--pale-cyan-blue: #8ed1fc;--wp--preset--color--vivid-cyan-blue: #0693e3;--wp--preset--color--vivid-purple: #9b51e0;--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple: linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%);--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan: linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%);--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange: linear-gradient(135deg,rgba(252,185,0,1) 0%,rgba(255,105,0,1) 100%);--wp--preset--gradient--luminous-vivid-orange-to-vivid-red: linear-gradient(135deg,rgba(255,105,0,1) 0%,rgb(207,46,46) 100%);--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray: linear-gradient(135deg,rgb(238,238,238) 0%,rgb(169,184,195) 100%);--wp--preset--gradient--cool-to-warm-spectrum: linear-gradient(135deg,rgb(74,234,220) 0%,rgb(151,120,209) 20%,rgb(207,42,186) 40%,rgb(238,44,130) 60%,rgb(251,105,98) 80%,rgb(254,248,76) 100%);--wp--preset--gradient--blush-light-purple: linear-gradient(135deg,rgb(255,206,236) 0%,rgb(152,150,240) 100%);--wp--preset--gradient--blush-bordeaux: linear-gradient(135deg,rgb(254,205,165) 0%,rgb(254,45,45) 50%,rgb(107,0,62) 100%);--wp--preset--gradient--luminous-dusk: linear-gradient(135deg,rgb(255,203,112) 0%,rgb(199,81,192) 50%,rgb(65,88,208) 100%);--wp--preset--gradient--pale-ocean: linear-gradient(135deg,rgb(255,245,203) 0%,rgb(182,227,212) 50%,rgb(51,167,181) 100%);--wp--preset--gradient--electric-grass: linear-gradient(135deg,rgb(202,248,128) 0%,rgb(113,206,126) 100%);--wp--preset--gradient--midnight: linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%);--wp--preset--duotone--dark-grayscale: url('#wp-duotone-dark-grayscale');--wp--preset--duotone--grayscale: url('#wp-duotone-grayscale');--wp--preset--duotone--purple-yellow: url('#wp-duotone-purple-yellow');--wp--preset--duotone--blue-red: url('#wp-duotone-blue-red');--wp--preset--duotone--midnight: url('#wp-duotone-midnight');--wp--preset--duotone--magenta-yellow: url('#wp-duotone-magenta-yellow');--wp--preset--duotone--purple-green: url('#wp-duotone-purple-green');--wp--preset--duotone--blue-orange: url('#wp-duotone-blue-orange');--wp--preset--font-size--small: 13px;--wp--preset--font-size--medium: 20px;--wp--preset--font-size--large: 36px;--wp--preset--font-size--x-large: 42px;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-color{color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-color{color: var(--wp--preset--color--white) !important;}.has-pale-pink-color{color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-color{color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-color{color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-color{color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-color{color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-color{color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-color{color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-color{color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-color{color: var(--wp--preset--color--vivid-purple) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-background-color{background-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-pale-pink-background-color{background-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-background-color{background-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-background-color{background-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-background-color{background-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-background-color{background-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-background-color{background-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-background-color{background-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-background-color{background-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-background-color{background-color: var(--wp--preset--color--vivid-purple) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-border-color{border-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-pale-pink-border-color{border-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-border-color{border-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-border-color{border-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-border-color{border-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-border-color{border-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-border-color{border-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-border-color{border-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-border-color{border-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-border-color{border-color: var(--wp--preset--color--vivid-purple) !important;}.has-vivid-cyan-blue-to-vivid-purple-gradient-background{background: var(--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple) !important;}.has-light-green-cyan-to-vivid-green-cyan-gradient-background{background: var(--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan) !important;}.has-luminous-vivid-amber-to-luminous-vivid-orange-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange) !important;}.has-luminous-vivid-orange-to-vivid-red-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-orange-to-vivid-red) !important;}.has-very-light-gray-to-cyan-bluish-gray-gradient-background{background: var(--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray) !important;}.has-cool-to-warm-spectrum-gradient-background{background: var(--wp--preset--gradient--cool-to-warm-spectrum) !important;}.has-blush-light-purple-gradient-background{background: var(--wp--preset--gradient--blush-light-purple) !important;}.has-blush-bordeaux-gradient-background{background: var(--wp--preset--gradient--blush-bordeaux) !important;}.has-luminous-dusk-gradient-background{background: var(--wp--preset--gradient--luminous-dusk) !important;}.has-pale-ocean-gradient-background{background: var(--wp--preset--gradient--pale-ocean) !important;}.has-electric-grass-gradient-background{background: var(--wp--preset--gradient--electric-grass) !important;}.has-midnight-gradient-background{background: var(--wp--preset--gradient--midnight) !important;}.has-small-font-size{font-size: var(--wp--preset--font-size--small) !important;}.has-medium-font-size{font-size: var(--wp--preset--font-size--medium) !important;}.has-large-font-size{font-size: var(--wp--preset--font-size--large) !important;}.has-x-large-font-size{font-size: var(--wp--preset--font-size--x-large) !important;}
</style>
<link rel='stylesheet' id='pc_google_analytics-frontend-css' href='https://benjiweber.co.uk/blog/wp-content/plugins/pc-google-analytics/assets/css/frontend.css?ver=1.0.0' type='text/css' media='all' />
<link rel='stylesheet' id='select-and-tweet-css' href='https://benjiweber.co.uk/blog/wp-content/plugins/select-and-tweet/select-and-tweet.css?ver=6.0.5' type='text/css' media='all' />
<link rel='stylesheet' id='wp-syntax-css-css' href='https://benjiweber.co.uk/blog/wp-content/plugins/wp-syntax/css/wp-syntax.css?ver=1.1' type='text/css' media='all' />
<link rel='stylesheet' id='bootstrap-css' href='https://benjiweber.co.uk/blog/wp-content/themes/wordpress-bootstrap/library/css/bootstrap.css?ver=1.0' type='text/css' media='all' />
<link rel='stylesheet' id='bootstrap-responsive-css' href='https://benjiweber.co.uk/blog/wp-content/themes/wordpress-bootstrap/library/css/responsive.css?ver=1.0' type='text/css' media='all' />
<link rel='stylesheet' id='wp-bootstrap-css' href='https://benjiweber.co.uk/blog/wp-content/themes/wordpress-bootstrap/style.css?ver=1.0' type='text/css' media='all' />
<script type='text/javascript' src='https://benjiweber.co.uk/blog/wp-content/themes/wordpress-bootstrap/library/js/libs/jquery-1.7.1.min.js?ver=1.7.1' id='jquery-js'></script>
<script type='text/javascript' src='https://benjiweber.co.uk/blog/wp-content/plugins/pc-google-analytics/assets/js/frontend.min.js?ver=1.0.0' id='pc_google_analytics-frontend-js'></script>
<script type='text/javascript' src='https://benjiweber.co.uk/blog/wp-content/themes/wordpress-bootstrap/library/js/bootstrap.min.js?ver=6.0.5' id='bootstrap-js'></script>
<script type='text/javascript' src='https://benjiweber.co.uk/blog/wp-content/themes/wordpress-bootstrap/library/js/scripts.js?ver=6.0.5' id='wpbs-scripts-js'></script>
<script type='text/javascript' src='https://benjiweber.co.uk/blog/wp-content/themes/wordpress-bootstrap/library/js/modernizr.full.min.js?ver=6.0.5' id='modernizr-js'></script>
<link rel="https://api.w.org/" href="https://benjiweber.co.uk/blog/wp-json/" /><link rel="alternate" type="application/json" href="https://benjiweber.co.uk/blog/wp-json/wp/v2/posts/768" /><link rel='shortlink' href='https://benjiweber.co.uk/blog/?p=768' />
<link rel="alternate" type="application/json+oembed" href="https://benjiweber.co.uk/blog/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fbenjiweber.co.uk%2Fblog%2F2015%2F03%2F21%2Fminimising-the-risk-of-data-damage%2F" />
<link rel="alternate" type="text/xml+oembed" href="https://benjiweber.co.uk/blog/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fbenjiweber.co.uk%2Fblog%2F2015%2F03%2F21%2Fminimising-the-risk-of-data-damage%2F&#038;format=xml" />
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-5518248-1', 'auto');
ga('send', 'pageview');
</script>
<link rel="amphtml" href="https://benjiweber.co.uk/blog/2015/03/21/minimising-the-risk-of-data-damage/amp/"><link rel="icon" href="https://benjiweber.co.uk/blog/wp-content/uploads/2025/01/benji2019.png" sizes="32x32" />
<link rel="icon" href="https://benjiweber.co.uk/blog/wp-content/uploads/2025/01/benji2019.png" sizes="192x192" />
<link rel="apple-touch-icon" href="https://benjiweber.co.uk/blog/wp-content/uploads/2025/01/benji2019.png" />
<meta name="msapplication-TileImage" content="https://benjiweber.co.uk/blog/wp-content/uploads/2025/01/benji2019.png" />
<!-- end of wordpress head -->
<!-- theme options from options panel -->
<style>
h1, h2, h3, h4, h5, h6{
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
font-weight: normal;
color: ;
}
body{
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
font-weight: normal;
color: ;
}
.hero-unit {
background-color: #ffffff;
}
#main article {
border-bottom: none;
}.container-fluid {
font-size: calc(var(--font_size_body_desktop, 19px) + var(--font_size_body_offset, 0px));
line-height: 1.6em;
}
#main article footer {
margin-top: 32px;
}
iframe, figure {
max-width: 100%;
overflow:hidden;
}
#sidebar1 {
padding-top: 145px;
}
@media (min-width: 2000px) {
#content { width: 137% }
}
#sidebar1 ul {
list-style-type: none;
margin: 0;
border-radius: 5px;
}
#sidebar1 li {
padding: 10px 0 10px 0;
}
.widgettitle {
font-size: 24px;
}
#benjimeta {
border-radius: 5%;
width: 48px;
margin: 0 10px 0 0;
}
</style>
</head>
<body class="post-template-default single single-post postid-768 single-format-standard">
<header role="banner">
<div id="inner-header" class="clearfix">
<div id="navbar">
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a data-target=".nav-collapse" data-toggle="collapse" class="btn btn-navbar">
<a href="http://benjiweber.co.uk" class="brand">
Benji Weber
</a>
<div class="nav-collapse">
<ul class="nav">
<li id="rxhp42e5294">
<a href="http://benjiweber.co.uk/">
About
</a>
</li>
<li id="rxhp42e5294" class="active">
<a href="http://benjiweber.co.uk/blog">
Blog
</a>
</li>
<li id="rxhp42e209e">
<a href="http://benjiweber.co.uk/cv">
CV
</a>
</li>
<li><a href="http://benjiweber.co.uk/talks">Talks</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div> <!-- end #inner-header -->
</header> <!-- end header -->
<div class="container-fluid">
<div id="content" class="clearfix row-fluid">
<div id="main" class="span8 clearfix" role="main">
<article id="post-768" class="clearfix post-768 post type-post status-publish format-standard hentry category-conferences category-continuousdelivery category-xp" role="article" itemscope itemtype="http://schema.org/BlogPosting">
<header>
<div class="page-header"><h1 class="single-title" itemprop="headline">Minimising the Risk of Data Damage</h1></div>
</header> <!-- end article header -->
<section class="post_content clearfix" itemprop="articleBody">
<p class="lead">One of the more interesting questions that came up at <a href="http://pipelineconf.info">Pipeline Conference</a> was:</p>
<h3><em>&#8220;How can we mitigate the risk of releasing a change that damages our data?&#8221;</em></h3>
<p>When we have a database holding data that may be updated and deleted, as well as inserted/queried, then there’s a risk of releasing a change that causes the data to be mutated destructively. We could lose valuable data, or worse &#8211; have incorrect data upon which we make invalid business decisions.</p>
<p>Point in time backups are insufficient. For many organisations, simply being unable to access the missing or damaged data for an extended period of time while a backup is restored, would have an enormous cost. Invalid data used to make business decisions could also result in a large loss.</p>
<p>Worse, with most kinds of database it’s much harder to roll back the database to a point in time, than it is to roll-back our code. It’s also hard to or isolate and roll-back the bad data, while retaining the good data inserted since a change.</p>
<p>How can we avoid release-paralysis when there’s risk of catastrophic data damage if we release bad changes? </p>
<p>Practices like having good automated tests and pair programming may reduce the risk of releasing a broken change &#8211; but in the worst-case scenario where they don&#8217;t catch a destructive bug, how can we mitigate its impact?</p>
<p>Here’s some techniques I think can help.</p>
<h3>Release more Frequently</h3>
<p>This may sound counter-intuitive. If every release we make has a risk of damaging our data, surely releasing more frequently increases that risk?</p>
<p>There has been <a href="http://www.alwaysagileconsulting.com/more-releases-with-less-risk/">lots written</a> about this. The reality seems to be that the more frequent our releases, the smaller they are, which means the chances of one causing a problem are reduced. </p>
<p>We are able to reason about the impact of a tiny change more easily than a huge change. This helps us to think through potential problems when reviewing before deployment.</p>
<p>We’re also more easily able to confirm that a small change is behaving as expected in production. Which means we should notice any undesirable behaviour more quickly. Especially if we are practising <a href="http://benjiweber.co.uk/blog/2015/03/02/monitoring-check-smells/">monitoring driven development</a>,</p>
<p>Attempting to release more frequently will likely force you to think about the risks involved in releasing your system, and consider other ways to mitigate them. Such as&hellip;</p>
<h3>Group Data by Importance</h3>
<p>Not all data is equally important. You probably care a lot that financial transactions are not lost or damaged, but you may not care quite so much whether you know when a user last logged into your system.</p>
<p>If every change you release is theoretically able to both update the user&#8217;s last logged in date, and modify financial transactions, then there’s some level of risk that it does the latter when you intended it to do the former.</p>
<p><img src="http://benjiweber.co.uk/datarisk-groupbyimportance.png" width="400"/></p>
<p>Simply using different credentials and permissions to control which parts of your system can modify what data, can increase your confidence in changing less critical parts of your system. Most databases support quite fine-grained permissions, to restrict what applications are able to do, and you can also physically separate different categories of data.</p>
<h3>Separate Reads from Writes</h3>
<p>If you separate the responsibilities of reading/writing data into separate applications (or even clearly separated parts of the same application), you can make changes to code that can only read data with more peace of mind, knowing there&#8217;s limits to how badly it can go wrong.</p>
<p><img src="http://benjiweber.co.uk/datarisk-cqrs.png"/></p>
<p><a href="http://martinfowler.com/bliki/CQRS.html">Command Query/Responsibility Separation</a> can also help simplifying conceptual models, and simplify certain performance problems.</p>
<h3>Make Important data Immutable</h3>
<p>If your data is very important, why allow it to be updated at all? If it can&#8217;t be changed, then there&#8217;s no risk of something you release damaging it.</p>
<p>There’s no reason you should ever need to alter a financial transaction or the fact that an event has occurred. </p>
<p>There are often performance reasons to have mutable data, but there&#8217;s rarely a reason that your canonical datastore needs to be mutable. </p>
<p>I like using <a href="http://engineering.linkedin.com/distributed-systems/log-what-every-software-engineer-should-know-about-real-time-datas-unifying">append-only logs</a> as the canonical source of data. </p>
<p><img src="http://benjiweber.co.uk/datarisk-eventsource.png"/></p>
<p>If changes to a data model are made by playing through an immutable log, then we can always recover data by replaying the log with an older snapshot.</p>
<p>If you have an existing system with lots of mutable database state, and you can&#8217;t easily change it, you may be able to get some of the benefits by using your database well. Postgres allows you to <a href="http://www.postgresql.org/docs/9.4/static/continuous-archiving.html">archive its Write-Ahead-Logs</a>. If you archive a copy of these you can use them to restore the state of the database at any arbitrary point in time, and hence recover data even if it was not captured in a snapshot backup.</p>
<h3 id="delayed_replicas">Delayed Replicas</h3>
<p>Let’s say we mess up really badly and destroy/damage data. Having good snapshot backups probably isn’t going to save us, especially if we have a lot of data. Restoring a big database from a snapshot can take a significant amount of time. You might even have to do it with your system offline or degraded, to avoid making the problem worse.</p>
<p>Some databases have a neat feature of <a href="http://www.postgresql.org/docs/9.4/static/standby-settings.html">delayed replcation</a>. This allows you to have a primary database, and then replicate changes to copies, some of which you delay by a specified amount of time. </p>
<p><img src="http://benjiweber.co.uk/datarisk-replicas.png"/></p>
<p>This gives you a window of opportunity to spot a problem. If you do spot a problem you have the option to failover to a slightly old version, or recover data without having to wait for a backup to restore. For example you could have a standby server that is 10 minutes delayed, another at 30mins, and another at an hour. </p>
<p><diagram of cascading replicas></p>
<p>When you notice the problem you can either failover to the replica or stop replication and merge selected data back from the replica to the master.</p>
<p>Even if your database can’t do this, you could also build it in at the application level. Particularly if your source of truth is a log or event-stream. </p>
<h3 id="verify_parallel">Verify Parallel Producers</h3>
<p>There will always be some changes that are riskier than others. It’s easy to shy away from updating code that deals with valuable data. This in turn makes the problem worse, it can lead to the valuable code being the oldest and least clean code in your system. Old and smelly code tends to be riskier to change and release.</p>
<p>Steve Smith described an application pattern called <a href="http://www.alwaysagileconsulting.com/application-pattern-verify-branch-by-abstraction/">verify branch by abstraction</a> that I have used successfully to incrementally replace consumers of data, such as reporting tools or complex calculations.</p>
<p>A variation of this technique can also be used to incrementally and safely make large, otherwise risky changes, to producers of data. i.e. things that might need to write to stores of important data and can potentially damage them. </p>
<p>In this case we fork our incoming data just before the point at which we want to make a change. This could be achieved by sending HTTP requests to multiple implementations of a service, by having two implementations of a service ingesting different event logs, or simply having multiple implementations of an interface within an application, one of which delegates to both the old and new implementation.</p>
<p><img src="http://benjiweber.co.uk/datarisk-parallel.png"/></p>
<p>At whatever stage we fork our input, we write the output to a separate datastore that is not yet used by our application.</p>
<p>We can then compare the old and new datastore after leaving it running in parallel for a suitable amount of time. </p>
<p>If we are expecting it to take some time to make our changes, it may be worth automating this comparison of old and new. We can have the application read from both the old and the new datastores, and trigger an alert if the results differ. If this is too difficult we could simply automate periodic comparisons of the datastores themselves and trigger alerts if they differ.</p>
<h3>Summary</h3>
<p>If you’re worried about the risk to your data of changing your application, look at how you can change your design to reduce the risk. Releasing less frequently will just increase the risk.</p>
</section> <!-- end article section -->
<footer>
<style type="text/css">a.bsky-follow-button:hover{ background: rgb(16, 131, 254) !important; }</style>
<a class="bsky-follow-button" href="https://bsky.app/profile/benjiweber.com" style="background: linear-gradient(135deg, rgb(90, 113, 250), rgb(0, 133, 255)); color: white; font-size: 13pt; padding: 5px 15px; 10px; 5px; display: inline-block; border-radius: 10px; height:32px; ">
<div style="display:inline-block; float: left;"><?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg style="margin: 5px; display:inline-block; width: 24px; height:24px;" viewBox="0 0 512 512" version="1.1" id="svg1" sodipodi:docname="bluesky-brands-solid.svg" inkscape:version="1.4 (e7c3feb100, 2024-10-09)" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> <defs id="defs1" /> <sodipodi:namedview id="namedview1" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:showpageshadow="2" inkscape:pageopacity="0.0" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" inkscape:zoom="3.8125" inkscape:cx="256" inkscape:cy="256" inkscape:window-width="5120" inkscape:window-height="2132" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" inkscape:current-layer="svg1" /> <!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--> <path d="M111.8 62.2C170.2 105.9 233 194.7 256 242.4c23-47.6 85.8-136.4 144.2-180.2c42.1-31.6 110.3-56 110.3 21.8c0 15.5-8.9 130.5-14.1 149.2C478.2 298 412 314.6 353.1 304.5c102.9 17.5 129.1 75.5 72.5 133.5c-107.4 110.2-154.3-27.6-166.3-62.9l0 0c-1.7-4.9-2.6-7.8-3.3-7.8s-1.6 3-3.3 7.8l0 0c-12 35.3-59 173.1-166.3 62.9c-56.5-58-30.4-116 72.5-133.5C100 314.6 33.8 298 15.7 233.1C10.4 214.4 1.5 99.4 1.5 83.9c0-77.8 68.2-53.4 110.3-21.8z" id="path1" style="fill:#ffffff" /></svg></div>
<span style="display: inline-block;">Follow @benjiweber</span>
</a>
<!--<a class="twitter-share-button" href="https://twitter.com/intent/tweet" data-size="large">Tweet</a>
<a href="https://twitter.com/benjiweber" class="twitter-follow-button" data-show-count="false" data-size="large">Follow @benjiweber</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script> -->
</footer> <!-- end article footer -->
</article> <!-- end article -->
<!-- You can start editing here. -->
<!-- If comments are open, but there are no comments. -->
<section id="respond" class="respond-form">
<h3 id="comment-form-title">Leave a Reply</h3>
<div id="cancel-comment-reply">
<p class="small"><a rel="nofollow" id="cancel-comment-reply-link" href="/blog/2015/03/21/minimising-the-risk-of-data-damage/#respond" style="display:none;">Cancel</a></p>
</div>
<form action="https://benjiweber.co.uk/blog/wp-comments-post.php" method="post" class="form-vertical" id="commentform">
<ul id="comment-form-elements" class="clearfix">
<li>
<div class="control-group">
<label for="author">Name (required)</label>
<div class="input-prepend">
<span class="add-on"><i class="icon-user"></i></span><input type="text" name="author" id="author" value="" placeholder="Your Name" tabindex="1" aria-required='true' />
</div>
</div>
</li>
<li>
<div class="control-group">
<label for="email">Mail (required)</label>
<div class="input-prepend">
<span class="add-on"><i class="icon-envelope"></i></span><input type="email" name="email" id="email" value="" placeholder="Your Email" tabindex="2" aria-required='true' />
<span class="help-inline">(will not be published)</span>
</div>
</div>
</li>
<li>
<div class="control-group">
<label for="url">Website</label>
<div class="input-prepend">
<span class="add-on"><i class="icon-home"></i></span><input type="url" name="url" id="url" value="" placeholder="Your Website" tabindex="3" />
</div>
</div>
</li>
</ul>
<div class="clearfix">
<div class="input">
<textarea name="comment" id="comment" placeholder="Your Comment Here…" tabindex="4"></textarea>
</div>
</div>
<div class="form-actions">
<input class="btn btn-primary" name="submit" type="submit" id="submit" tabindex="5" value="Submit Comment" />
<input type='hidden' name='comment_post_ID' value='768' id='comment_post_ID' />
<input type='hidden' name='comment_parent' id='comment_parent' value='0' />
</div>
</form>
</section>
</div> <!-- end #main -->
<div id="sidebar1" class="fluid-sidebar sidebar span4" role="complementary">
<div id="recent-posts-3" class="widget widget_recent_entries">
<h4 class="widgettitle">More Articles</h4>
<ul>
<li>
<a href="https://benjiweber.co.uk/blog/2025/07/14/teamwork-xp-in-the-era-of-genies/">Teamwork &#038; XP in the era of Genies</a>
</li>
<li>
<a href="https://benjiweber.co.uk/blog/2025/01/01/overcoming-resistance-to-extreme-programming/">Overcoming Resistance to Extreme Programming</a>
</li>
<li>
<a href="https://benjiweber.co.uk/blog/2023/11/12/tragedy-of-return-to-hostile-offices/">Tragedy of Return to Hostile Offices</a>
</li>
<li>
<a href="https://benjiweber.co.uk/blog/2023/10/15/engineering-team-lessons-from-cycling/">Engineering Team Lessons from Cycling</a>
</li>
<li>
<a href="https://benjiweber.co.uk/blog/2023/10/15/one-does-not-simply-deliver-software/">One does not simply deliver software</a>
</li>
<li>
<a href="https://benjiweber.co.uk/blog/2022/10/08/do-you-need-a-strong-leader/">Do you need a Strong Leader?</a>
</li>
<li>
<a href="https://benjiweber.co.uk/blog/2022/01/30/supporting-sustainability/">Supporting Sustainability</a>
</li>
<li>
<a href="https://benjiweber.co.uk/blog/2022/01/30/pondering-agile-principles/">Pondering Agile Principles</a>
</li>
<li>
<a href="https://benjiweber.co.uk/blog/2022/01/12/cost-of-attrition/">Cost of Attrition</a>
</li>
<li>
<a href="https://benjiweber.co.uk/blog/2021/07/03/uncovering-better-ways/">Uncovering Better Ways</a>
</li>
<li>
<a href="https://benjiweber.co.uk/blog/2021/04/10/dont-hire-top-talent-hire-for-weaknesses/">Don&#8217;t hire top talent; hire for weaknesses.</a>
</li>
<li>
<a href="https://benjiweber.co.uk/blog/2021/03/28/escape-the-permission-trap-with-healthy-habits/">Escape the Permission Trap with Healthy Habits</a>
</li>
<li>
<a href="https://benjiweber.co.uk/blog/2021/03/21/thinking-in-questions-with-sql/">Thinking in Questions with SQL</a>
</li>
<li>
<a href="https://benjiweber.co.uk/blog/2021/03/14/leadership-language-lessons-from-star-trek/">Leadership Language Lessons from Star Trek</a>
</li>
<li>
<a href="https://benjiweber.co.uk/blog/2021/03/14/java-16-pattern-matching-fun/">Java 16 Pattern Matching Fun</a>
</li>
<li>
<a href="https://benjiweber.co.uk/blog/2021/03/07/we-got-lucky/">We got lucky</a>
</li>
<li>
<a href="https://benjiweber.co.uk/blog/2021/02/28/revisiting-html-in-java/">Revisiting Html in Java</a>
</li>
<li>
<a href="https://benjiweber.co.uk/blog/2021/02/06/meetings-ugh-lets-change-our-language/">Meetings, ugh! Let&#8217;s change our language</a>
</li>
<li>
<a href="https://benjiweber.co.uk/blog/2021/01/23/latency-numbers-every-team-should-know/">Latency Numbers Every Team Should Know</a>
</li>
<li>
<a href="https://benjiweber.co.uk/blog/2020/11/22/humility/">Humility</a>
</li>
<li>
<a href="https://benjiweber.co.uk/blog/2020/10/03/sealed-java-state-machines/">Sealed Java State Machines</a>
</li>
<li>
<a href="https://benjiweber.co.uk/blog/2020/09/19/a-little-rant-about-talent/">A little rant about talent</a>
</li>
<li>
<a href="https://benjiweber.co.uk/blog/2020/09/19/fun-with-java-records/">Fun with Java Records</a>
</li>
<li>
<a href="https://benjiweber.co.uk/blog/2020/09/12/the-benefits-of-making-code-worse/">The benefits of making code worse</a>
</li>
<li>
<a href="https://benjiweber.co.uk/blog/2020/09/06/reasons-to-hire-inexperienced-engineers/">Reasons to hire inexperienced engineers</a>
</li>
</ul>
</div>
<!--a href="https://twitter.com/benjiweber" class="twitter-follow-button" data-show-count="false" data-size="large">Follow @benjiweber</a-->
<style type="text/css">a.bsky-follow-button:hover{ background: rgb(16, 131, 254) !important; }</style>
<a class="bsky-follow-button" href="https://bsky.app/profile/benjiweber.com" style="background: linear-gradient(135deg, rgb(90, 113, 250), rgb(0, 133, 255)); color: white; font-size: 13pt; padding: 5px 15px; 10px; 5px; display: inline-block; border-radius: 10px; height:32px; ">
<div style="display:inline-block; float: left;"><?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg style="margin: 5px; display:inline-block; width: 24px; height:24px;" viewBox="0 0 512 512" version="1.1" id="svg1" sodipodi:docname="bluesky-brands-solid.svg" inkscape:version="1.4 (e7c3feb100, 2024-10-09)" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> <defs id="defs1" /> <sodipodi:namedview id="namedview1" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:showpageshadow="2" inkscape:pageopacity="0.0" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" inkscape:zoom="3.8125" inkscape:cx="256" inkscape:cy="256" inkscape:window-width="5120" inkscape:window-height="2132" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" inkscape:current-layer="svg1" /> <!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--> <path d="M111.8 62.2C170.2 105.9 233 194.7 256 242.4c23-47.6 85.8-136.4 144.2-180.2c42.1-31.6 110.3-56 110.3 21.8c0 15.5-8.9 130.5-14.1 149.2C478.2 298 412 314.6 353.1 304.5c102.9 17.5 129.1 75.5 72.5 133.5c-107.4 110.2-154.3-27.6-166.3-62.9l0 0c-1.7-4.9-2.6-7.8-3.3-7.8s-1.6 3-3.3 7.8l0 0c-12 35.3-59 173.1-166.3 62.9c-56.5-58-30.4-116 72.5-133.5C100 314.6 33.8 298 15.7 233.1C10.4 214.4 1.5 99.4 1.5 83.9c0-77.8 68.2-53.4 110.3-21.8z" id="path1" style="fill:#ffffff" /></svg></div>
<span style="display: inline-block;">Follow @benjiweber</span>
</a>
</div>
</div> <!-- end #content -->
<footer role="contentinfo">
<div id="inner-footer" class="clearfix">
<hr />
<div id="widget-footer" class="clearfix row-fluid">
<div id="meta-3" class="widget span4 widget_meta"><h4 class="widgettitle">Admin</h4>
<ul>
<li><a rel="nofollow" href="https://benjiweber.co.uk/blog/wp-login.php">Log in</a></li>
<li><a href="https://benjiweber.co.uk/blog/feed/">Entries feed</a></li>
<li><a href="https://benjiweber.co.uk/blog/comments/feed/">Comments feed</a></li>
<li><a href="https://wordpress.org/">WordPress.org</a></li>
</ul>
</div> </div>
<nav class="clearfix">
</nav>
<p class="pull-right"><a href="http://320press.com" id="credit320" title="By the dudes of 320press">320press</a></p>
<p class="attribution">&copy; Benji&#039;s Blog</p>
</div> <!-- end #inner-footer -->
</footer> <!-- end footer -->
</div> <!-- end #container -->
<!--[if lt IE 7 ]>
<script src="//ajax.googleapis.com/ajax/libs/chrome-frame/1.0.3/CFInstall.min.js"></script>
<script>window.attachEvent('onload',function(){CFInstall.check({mode:'overlay'})})</script>
<![endif]-->
<script type='text/javascript' src='https://benjiweber.co.uk/blog/wp-content/plugins/select-and-tweet/select-and-tweet.js?ver=1.0' id='select-and-tweet-js'></script>
<script type='text/javascript' src='https://benjiweber.co.uk/blog/wp-content/plugins/wp-syntax/js/wp-syntax.js?ver=1.1' id='wp-syntax-js-js'></script>
</body>
</html>
<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/
Served from: benjiweber.co.uk @ 2026-09-12 01:08:00 by W3 Total Cache
-->