Share post
I don’t contribute as much as I should to open source stuff, but there are on occasion some projects I take up that I feel somewhat passionate about. Whether it’s for some of my closer homies, or to help me with something mundane. Then there was that one time my city decided to build out an e-bike rental network, but created it in such a way that it was nearly unusable and my partner and I felt compelled to at least try and help make it salvageable. We were definitely a little inspired by the time a bunch of parents helped make an open school system for Stockholm that was more usable than the garbage the city created!
I want to tell this story because it involves a very ambitious government-funded project that was overall a great idea for the city, but had such engineering and logistics problem that it led me and my partner to try (and to many extents fail) to develop some tools available to everyone in Stockholm to make the experience better. I’ll talk about those problems, as well as what we did, and what the situation is today.
If you want to skip to just the stuff we did, you can go to the section Making Stockholm E-bikes usable. If not, enjoy the extra background!
A brief history of Stockholm Bike Projects
To many readers, the idea of a government-funded network of rentable bicycles is perhaps a silly concept. After all, why would you want to spend money for other people to have a temporary bike when they could just walk, drive, or buy their own bicycle?
Well, there are many reasons (at least here in Stockholm) that this can be good. First off, it’s great for locals because really unless you are commuting daily with a bike, you don’t need to own and it is nice to have the option of a cheap transport without needing to deal with the cost of owning, plus figuring out storage, etc. Secondly, it can be good for tourism in the summers where a nice bike ride around the city can be an enjoyable experience. Private rental companies exist, of course, but Stockholm is large and the need definitely outmatches supply of rentable bicycles.
It all started for Stockholm in the 1970s
The first rental setup was created in limited form in the 1970s where you could visit an office created by an environment group where you would write your name and address, and you get a bike for 24 hours. Amazing! This was also slightly political, since at the time there was a push to make cars more central to planning the city, but they pushed hard for bikes instead!
Between then and now there have been a bunch of attempts to kick off organized rental services, but there were not really any true city-wide networks until around the 1990s where there started to be some organized form of rentals. These “newer” rental bike systems were basically a security-deposit system where you insert your money and you get a bike for some time. Take the bike back, and you get your money back. That worked for some time, but those systems, too, came and went. By the way, this information is hard to come by so massive shout out to Isa Eriksson for this Master’s thesis that helped a bunch on the history!
Technology on the rise!
After the 2000s, we started to see a lot of technology creep into places where it was otherwise unexpected. Tracking systems became easier, we had smart cards that you could purchase for the metros, etc. So it was natural this was tried in bike rentals as well. Indeed, in those times a company that partnered with the city used pre-loadable rental cards you could use to take bikes similar to the deposit system from the 90s. This then-used rental system also survived to make it through a transition to app-based rentals of the bikes which is a very nice long run!
But then, electric vehicles became more and more popular as time went on, and everyone started to get in on this new trend! so then came the idea: E-bikes! Bikes with electric motors that could make cycling around this big and hilly city much easier! It wasn’t long before Stockholm decided they would want a bicycle system that was based on e-bikes. So around 2016 or so they started planning the phase-out of the older system that had worked since 2006 or so, and begin taking contracts for a newer e-bike system. This worked out well since there were indications that the existing system was in danger due to increasing bike thefts and vandalism. While these problems were certainly solvable, the decision to plan retirement was already made. This is where I get the pleasure to introduce you to the first attempt at this new system and why it failed to meet the mark.
The Stockholm Rental e-Bike Ambition
This idea was fairly simple: put out a call for bids on E-bikes and a system to rent them to Stockholmers and tourists. The contract was for 400 million Swedish crowns (about $40 million) to be budgeted over 7 years, and in the end there were two major contenders:
- Voi (based in Sweden)
- 7500 bikes
- Marfina (based in Spain)
- 5000 bikes
The first delivery was to be April of 2022. Both competitors promised some thousands of bikes within the given timeline, and the city initially decided that Voi would win the contract. However, there was a closer review initiated, which then tipped things in favor of Marfina. Now there is some spicy drama around the fact that the partner of Marfina that perhaps initiated this through pressure was Clear Channel, the ad company that partnered also with City Bikes. I won’t get into the politics, but you can probably look into and draw your own conclusions around this.
Regardless, we had a winner and Marfina got to work… sort of.
Subsidiary congo
In the world of risk and liability, subsidiaries are a helpful tool to hedge against potential loss because of problems, legally or otherwise. For a product, however, it can be a nightmare scenario for customers that only interact with the end of the chain and this will be important later. Marfina did not directly involve themselves in the actual development of the system, and they instead used a subsidiary called Inurba Mobility that would deliver the bikes – which in turn also enlisted its own subsidiary called Stockholm E-Bikes which would operate them in Stockholm. In all of this there were TWO MORE partners involved called SEAT Mobility Labs in Spain which created the fleet management and rental apps, and Vaimoo in Italy which created the E-bike components.
If this is already hard to keep track of, I get it. To be honest I just ignore Marfina and separate the rest into their responsibilities:
- Vaimoo – created the E-bike components
- There was some polish company involved as well, but I can’t be arsed to dig that far.
- Inurba Mobility – assembled and delivered the E-bikes
- SEAT Mobility Labs – developed the app and website
- Stockholm E-Bikes – oversaw operations in Stockholm
Now I admit that a lot of this is hard to find info on, so it may be there are parts of this I can be corrected on, and if that is the case, please do correct me and send me an email at birdhalfbaked@gmail.com
A rocky 2022 rollout
With all the companies playing a role together, surely things went smoothly to meet the deadline for first delivery right? WRONG
Supply issues
It could not have been more disastrous. First off… I think everyone that was alive during 2022 knows this was chaotic because of Covid-19 causing logistics issues across the world for parts production. This meant there were not enough resources to create the E-bikes required for initial rollout. No bikes, no service.
You also don’t want to start servicing with too few bikes. In fact that would be worse. People were waiting for this, and imagine they tried to use this system with only a handful of bikes available meaning people would need to just get lucky to find a bike. Many of us probably would default to saying, “Screw it!” Unhappy customers is significantly less ideal than no customers in this situation. Naturally, they pushed back the delivery dates as needed to meet the required initial supply.
Okay, supply solved, let’s get started
Eventually, however, we did get the bikes and it was rolled out with an app that allowed people to get started with renting bikes. When you opened the app you were presented with a splash screen showing the Stockholm eBikes logo.
After that you’d register and you had a fairly expected screen showing the map of all bike stations and locations. Clicking on a station would show you available bikes, and even let you reserve a bike. You would then be able to unlock bikes through scanning a QR code when you arrived at the bike.
Where were the bikes?
Now we get to the first major technical problem. When you would go into the app to see the stations, you might see there are 9/10 bikes at the station. You take this at face value of course, and walk to the station to grab the bike. Maybe you even reserved it. However, when you arrive at the station you find that there are no bikes.
This was not something that happened periodically, either. This is something that happened at least 50% of the time. That is, it was a literal coin toss on whether you could find a bike at the station where it should be according to the app. Never have we felt more gaslit than when using that app.
On top of all of this, there was no incentive to force users to leave bikes at the station (lol). So naturally we had what I call the shopping cart problem. The thing that made this breaking for the system was that the maps did not show any of the bikes outside of stations.
This was fixed later on (like a season later), but when it was rolled out as a system, this was a big issue.
Some bikes wouldn’t unlock
Okay, so you’re lucky enough to arrive at a station and you see there is actually a bike available! Truly the gods have shined upon you! You grab the app, and use the QR scanning feature to unlock the bike and start your journey.
But what’s this? You can’t unlock it! The app pretends like nothing is happening.
This was absolutely infuriating when it hit you. And that was also quite frequently. I don’t think there needs to be more focus on this part, and to be honest I feel myself really getting heated remembering the experiences I had with this.
Making Stockholm eBikes usable
Okay so to recap, the company providing Stockholm eBikes after handling supply issues created an app and fleet service that created a horrible user experience when trying to use the system. There were two major issues:
- Bikes weren’t at the station even though the app said they were
- Bikes did not reliably unlock
Follow the data
Usually the most important aspect of problem solving is collecting evidence that associates to each problem. If you can detect related data, you can help solve, or at least better indicate what is the expected behavior of some system. So this is where I start almost always with such things.
In most mobile applications, you usually have a source of data that can be used to display for the user. Given my background was data engineering and my partner is a data scientist, and we both have extensive experience in the field for various industries, it was fairly easy to retrieve the data was loaded into the app and manipulate it into a way that we could dive deep (AWS folks get the reference lol).
Upon inspecting what data was sent back and forth from the app and the servers that tracked the fleet data, we had a fun realization: all of the fleet data was publicly accessible without any authorization.
We had details on the bikes themselves:
- last update time – when the bike last sent telemetry to the fleet servers
- last connection time – when the bike was last interacted with by a user
- last maintenance time – when the bike was last taken to maintenance
- condition – anything other than empty indicated a problem and it was free-text and could say truly anything
- status +
- lock status – locked vs unlocked
- energy % – battery level
- geographic coordinates – the coordinates of the bike’s current known location
- license plate #
And we also had information per station:
- name – the station’s local name
- address – street address
- geographic coordinates – the latitude and longitude info
- bikes available – list of bikes that were registered to each station
An important note here is that bike locations were obscured when they were unlocked for use.
It was pretty easy to make a quick service to just grab this info periodically (every 5 minutes) and catalog it for use. That part of the ingestion pipeline took about an hour (this is my wheelhouse, and I am quite good at wheeling in my wheelhouse.)
I aggregated all of this into relevant data tables that also kept historic logs of the data relevant to us, including analysis of things like connection times, maintenance times, and energy levels so we could track drain rates etc. All of the data was just snapshots of “now” so it was important to do this logging ourselves.
Now since this was meant to be a “fun” project I didn’t track things as well as I should have. To be honest I did not expect to ever really tell this story either. However, here is a link to a database backup we had kept while we were testing things: https://drive.google.com/file/d/116DWnpuIHkLi3Dm2LsSHS6KDQm3uLKof/view?usp=drive_link
Understanding the problems in detail
Bikes not being at the station
So first in that problem list was stations reporting that the bikes were at the station, when in reality they were not. So for this it was the goal to see where those bikes actually were. This was actually fairly easy to be honest since we had the location info from the bikes when they were locked.
I mean that was it really… we definitely didn’t expect location data to be so easy to come by, but hey we don’t look a gifted horse in the mouth eh? Looking at the data we could determine that the bikes were just registered as a fleet vehicle at only one station. So from then on all we had to do was just look up the bicycle license number, then see where it actually was geographically using the lat-long coordinates.
So cool we decided to then start looking at if we could reliably see what was going on with the unlocking issue.
So what WAS up with the Unlocking issues?
A quick look at the data we had quickly uncovered that unlock statuses are just “closed” if the bike was in a locked state, and “open” if in an unlocked state (meaning in-use).
Saving the boring steps of analyzing the data further, we found two issues. The first one was just when the battery was less than a certain percent, it wouldn’t unlock. But we also found an interesting behavior… Sometimes bikes would just… poof from the current snapshots of data. We knew this wasn’t because of people using them, because even when users were riding the bikes, we would still see them in our updates as having an “open” lock status. We checked the app using the license plate number and found out that the station would still register the bike as at the station.
This warranted a follow-up so we actually took each case at our nearest station and walked to it to see if we could see what happened with the bike.
LO AND BEHOLD! We could reserve those bikes and indeed they were at the physically at the station but they wouldn’t unlock. We tested this at least 6 or 7 times on various days, and yeah it held. We found the issue, and here’s what we thought was happening:
- Station bike lists were based on just IDs that it would pick up from the fleet service.
- Sometimes the fleet servers would just not “know” about the bike that corresponded (or more likely there was something internal that caused it to be filtered, maybe a bug, maybe something else).
- Scanning a bike would require that the server recognized the bike , but since the fleet servers wouldn’t acknowledge that bike the app couldn’t actually complete the flow for unlocking.
Uncovering an unintended easter-egg
While figuring out the issue around the issue with unlocking bikes failing, we also found some weird data points… We saw bikes that had location data, but also had an “open” lock status. Remember when I said this:
An important note here is that bike locations were obscured when they were unlocked for use.
Well… this was still true. It turns out that the bikes weren’t in use by users, but still somehow retained the open lock status anyway as if they were in use. This meant we could walk to any bike we found at their coordinates, and just… take them. Yeah, seriously. No pay needed :D.
To be clear, we did try to contact the company about this issue to no avail. To be honest, at this point they had so many issues I can imagine this was just lost.
We did think we were a bit crazy, so we made sure to spot check. I didn’t myself exploit this, but one can imagine not all pass up the opportunity.
Our suspicion for this behavior was actually that the locking would not work, and people would just give up and use the support function to stop their trip, but this would not lock the bike somehow. We tried to reproduce this, but could not reliably.
How to make all of this better?
Well, we couldn’t contact the company, and to be honest I don’t think we would get any good response anyway. Since most (all?) of the problems lied in server code we couldn’t ourselves patch, that left us with the option of band-aiding at least the information presented to users. For us, we decided to try and make a website that would help at least present more truthful information, and then help users to actually understand what bikes were available and how to get to them.
Neither of us are web designers, and to be quite honest we are pretty shit at it, so we decided to use this as a way to improve some skills there. We decided on using a frontend (fancy way to say “the visual part of development”) framework called Vue.js. We didn’t really know javascript, or this thing called typescript which it required I guess, but it was actually the most forgiving language(s) I had seen in a while. You can write the stupidest functions with zero type safety and the language just lets you.
We set up a small mobile-reactive website that showed front and center a more proper map of stations and bikes, with some better information presented when you clicked on the pins.
Our app had several advantages over the original app:
Show where the bikes actually are!
The first improvement is that we didn’t just show stations as pins. Instead we showed them as circular areas, and the pins were the bikes.
Make the other information first class
I do believe in making a lot of information flow better for a user. This was what we had pop up for the user on first load of the website:
We also made it clear the limitations of the system to help people understand the issues they may face. We couldn’t solve them for them, but at least the user would be informed.
And on top of that, the ability to just click on a bike and see what station it was actually associated with to reserve things was a huge plus. Here you can see a case we had of a bike that was left at a station completely different than its home, which led to confusion for users wanting to reserve the bike.
We also asked for feedback in person and online
We would often hang around stations watching people frustrate themselves with the system, then show them our website to see if it would help them. Some didn’t like it to be fair, but many did.
We also posted about this on reddit. It wasn’t super popular a post, but it got some comments we were able to answer info about.
I think the feedback aspect was super important at this point because again, we wanted the system to work, and we didn’t want to add to frustration here. To that end….
We made it extremely clear this was a third party project
We had to make sure that if we did cock things up, it would not reflect on the project itself, and that the city and the companies involved did not need to solve for other annoyances.
And the system was saved!
No. In fact the company did not have a good year, and even with the improvements to useability we made with our app (whether people used them or not), it couldn’t save the system from what turned out to have flaws structurally that had bikes falling apart during use, and causing some riders to be injured. Not to mention an issue that caused potential fire hazards during winter storage. Yikes! In the end, no amount of app magic will fix actual hazards in the product!
In the end, the company(ies) involved got slapped down… hard. Stockholm removed their contract entirely and to be honest the company never really recovered from the myriad of problems they faced. They were trying to address some, but to be honest it was still too little too late. I really wish I could link articles here in a general way people will be able to read this, but it’s all in Swedish unfortunately, but at least this twitter feed paints the story pretty well: https://x.com/StockholmeBikes
Currently there is another company that is partnering with the city to give e-bikes to the people, but they are more expensive and really I still wish Stockholm eBikes lived up to the hype they created given the cheap prize we got as residents. We’ll see if this new company holds its reign, but given the history of bike rentals in Stockholm, I don’t hold my breath, but I do stand ready should any more project opportunities come up to make things better. So far I haven’t seen anything really standing out, but I’m usually open to ideas that are pitched to me at various meetups. Thanks for reading!