Loosing your users' data —
the story of nine bytes

Igor Lukanin at Konfur, November 2015

What we have

Why NoSQL?

#1.
Users' accounts
are unrelated

#2.
One collection
vs. 30 tables

#3.
Less boilerplate
 

Company

            public Guid Id { get; set; }
            public string Inn { get; set; }
            public List<PaperDocument> PaperDocuments { get; set; }
            public List<RknNotification> RknNotifications { get; set; }
            // 42 more properties like this
        

ICompanyRepository

            void Remove(Guid id);
            void Save(Company company);
            Company Find(Guid id);
            Company FindByUid(string uid);
            IEnumerable<Company> FindByInn(string inn);
            IEnumerable<Company> FindWithRknNotifications();
            // 13 more methods like this
        

CompanyRepository

            public IEnumerable<Company> FindByInn(string inn) {
                return mongoCollection.AsQueryable()
                    .Where(company => company.Inn == inn)
                    .Select(Prepare);
            }
            // Many more complicated queries
        

CompanyRepository

            public void Save(Company company) {
                collection.Save(PrepareSave(company));
            }
        

Data calculation

            // Stored in database and Calculated data
            Stored0 + Calculated0 = Prepare    (Stored0)
            Stored1 + Calculated1 = Process     (Stored0 + Calculated0)
            Stored2               = PrepareSave(Stored1 + Calculated1)
        

Why?

#1.
Data duplication
 

#2.
Circular
references

Once upon a time...

CompanyRepository

            public IEnumerable<Company> FindAll()
                return mongoCollection.FindAll();
            }
        

Code review

Quality assurance

Deployed!

In two days
our tester spots
something...

Broken data calculation

            // Stored in database and Calculated data
            Stored0 + Calculated0 =              Stored0
            Stored1 + Calculated1 = Process     (Stored0 + Calculated0)
            Stored2               = PrepareSave(Stored1 + Calculated1)
        

Who is
responsible?

No backups

4530
accounts affected

#1. MS SQL

2170
accounts left

#2. pisa.exe

150
accounts left

#3. Assumptions
and speculations

150
accounts left

150 letters
to users

Two replies &
two phone calls

Outcomes

Data redundancy
 

Backups
 

Smoke testing
 

Code review
 

Infrastructure
crews

Shooting yourself
in the foot

Joy & pleasure
for everyone

Have failed?
Be vocal

@igorlukanin

Fork me on GitHub