Marshall Bowers

Conjurer of code. Devourer of art. Pursuer of æsthetics.

redux-persist-transform-encrypt (2016–2024)

Tuesday, April 23, 2024
1782 words
9 minute read

On February 2, 2024, I declared bankruptcy on an open-source project of mine: redux-persist-transform-encrypt.

This is a postmortem of sorts for that project. I'll detail how it came to be, developments that happened over the years, and the events that led to my eventual decision to shut it down.

Origins

Back in 2016 I was spending my days at work rebuilding our existing AngularJS frontend using React.

As part of this rewrite, we had chosen Redux as our state management solution, in part due to the incredible amount of hype it commanded in the React ecosystem at the time.

I can still remember watching Dan Abramov's "Live React: Hot Reloading with Time Travel" talk from react-europe 2015 and being wowed by the possibilities that Redux offered.

In the interest of making our application more tolerant to network interruptions, I started looking into redux-persist as a way to persist and rehydrate a Redux store using the browser's localStorage.

Given that we were dealing with student data and grade information, one of our requirements was that this data had to be secured at rest.

v1.0.0–v2.0.0

On May 14, 2016, I released the first version of redux-persist-transform-encrypt (b33f6cf).

The goal of the library was fairly simple: provide a transform for redux-persist that could encrypt a Redux store when persisting it to localStorage, and then decrypt it during dehydration. The store was encrypted using AES from crypto-js, secured by a secret key provided by the caller.

Given that this was all happening client-side, we would use a user-specific secret key returned from our API when the user signed in to read the encrypted contents of the store. Once the user signed out, the key would be evicted from memory and unavailable until they signed in again.

Work on the library progressed with some regularity for the next couple of years, with small improvements being made gradually in response to my needs at work.

I released v2.0.0 and v2.0.1 on April 2, 2018 (b5f99d6).

The shift

It was around this time that a shift occurred. We had stopped using Redux at work, having completed a (rather involved) migration to MobX.

Redux had a lot of papercuts when trying to write well-typed code in TypeScript, and we were also starting to see some performance issues when dispatching certain actions. After some trialing, MobX did better on both those fronts, and seemed like a clear win for us to adopt.

Along with the move to MobX, we also ditched the whole idea of local persistence, instead falling back to a more traditional "always online" approach.

The result of this was that I was left with no further use for redux-persist-transform-encrypt, and the library sat untouched.

React Native interlude

Pretty early on in redux-persist-transform-encrypt's lifetime—almost as soon as the first version was out in the wild—I started getting a lot of GitHub issues pertaining to using it with React Native.

Not being a React Native user myself, I tried to support the use case as best I could. I setup a React Native example app in the repo (dceb475) so I could reproduce issues reported on React Native.

This will be important later on.

v3.0.0

On October 16, 2020, I merged a PR titled "Total overhaul", which did exactly what it said on the tin (f6614c7).

I had rewritten the codebase in TypeScript, modernized it, and fixed a number of issues from the backlog that had piled up in the interim two years.

In the PR description I wrote:

This library has been stagnating for a long while. This PR gives redux-persist-transform-encrypt some much-needed love and fixes/obviates a number of issues that have cropped up over time.

At this point in time the repository had accumulated 277 stars, far more than any of my other repositories, and I felt an obligation to continue maintaining it.

Hiatus and v4.0.0

After releasing v3.0.0 (and a subsequent patch release) I went on hiatus from my maintainer duties for a while.

I returned on July 28, 2022, to do some housekeeping—mainly dependency bumps—and released v4.0.0 (9565c01).

One of the issues prompting the release of v4.0.0 was updating crypto-js to v4.1.1 to fix a security vulnerability. Unfortunately, this update caused more problems on React Native, due to crypto-js not playing nice with React Native environments. The PR to fix this, brix/crypto-js#259, is still open four years later.

v5.0.0

On March 24, 2023, I returned again to do some more housekeeping. This time a bigger change was made: the switch to ES Modules (ESM).

At this point in time the ESM discourse was all over the place. Package authors were trying to navigate landscape of deciding whether to migrate their packages to ESM, or go down the rabbit hole of dual-hosting CommonJS and ESM.

JavaScript package behemoth Sindre Sorhus had been putting out new major versions of his packages that were ESM-only, linking out to a gist titled "Pure ESM package" letting package consumers know what they needed to do to consume a pure ESM package.

After evaluating my options, I opted to go the pure ESM route. After all, ESM support was generally less of a problem for frontend projects, as most bundlers had good support for ESM (the same of which could not be said for backend projects).

I published v5.0.0 (682f0d8) with the new ESM support, dropping support for CommonJS in the process.

Shortly after releasing v5.0.0 I started seeing an influx of GitHub issues stemming from issues using the new version on React Native. This time it was due to the ESM changes.

Amongst the issues were also pull requests trying to fix the ESM issues with React Native, but they all seemed like application authors doing whatever worked to fix their specific use case, with seemingly little regard for what other impact their changes might have.

At this point I was starting to get frustrated with having to try to troubleshoot this issue in the dark. I put out a call for a reproduction on one of the issues so I could test out any changes and hopefully put this to rest:

If someone could provide a repo with a reproduction of the issue that would be immensely helpful for getting it resolved.

I don't use React Native, redux-persist, or redux-persist-transform-encrypt anymore, so I don't have anywhere to effectively test any potential fixes.

I never received a reproduction.

Bankruptcy

On February 2, 2024, I received a GitHub notification from one of the open ESM-related PRs with the PR author tagging me for a review. That notification ended up being the last straw.

I knew I couldn't keep going on maintaining a library that I hadn't used in seven years.

So I made the decision to shut it all down, updating the README with the following notice:

As of February 2, 2024, I will longer be maintaining redux-persist-transform-encrypt.

I have been supporting it as best I can these past few years, but the reality of it is I have not used redux-persist-transform-encrypt, redux-persist, or Redux since 2017.

Since I no longer use any of the technologies involved and don't have a good way of testing any potential changes, I am no longer in a position where I feel I can maintain this package to my desired standards.

Additionally, redux-persist as a project also seems dead, despite an attempted change in management.

Then I archived all the open issues and PRs and, finally, the repo itself.

A final review

By the end of its run, redux-persist-transform-encrypt had accumulated 359 stars, and is still my most-starred repo.

star history

The unexpected popularity of the library—combined with my own personal vanity towards silly internet points—was a large part of what kept me going so long.

For a while it felt like I could keep things in stasis forever. I suspect I likely could have—at least for a little while longer—had I not gone through with the ESM change. After all, it doesn't take a terrible amount of effort to return every so often, do a bit of housekeeping, ship a new version, and then disappear again.

But it was the reality of the ESM change and the subsequent fallout that made me reckon with some things.

Back when I started this project, I was still a junior engineer hoping to make a name for himself. So when redux-persist-transform-encrypt gained some amount of traction, I felt I had to ride it as long as I could.

Now I'm at a much different place in my career, and don't much care to be known for a tiny JavaScript library.

Another factor that weighed in on my decision was the state of the redux-persist ecosystem as a whole. To be blunt, redux-persist is dead.

The last commit to the redux-persist repository by its original author was on September 1, 2019. There was an attempted change in management in September 2021, but that seems to have petered out as well.

As I write this, the last commit to the redux-persist repository was on November 22, 2021, going on three years ago.


There's probably a dozen different things I could have done differently over the lifetime of this project.

Could I have put in a bit more work to reproduce and troubleshoot user issues? Sure. Could I have found additional maintainers to help out or take over when I was ready to move on? Perhaps.

At the end of the day, I think there's something to be said for knowing when to throw in the towel. So that's what I did.

If you were a redux-persist-transform-encrypt user, thank you. I hope you found it useful for the time that you did.