A picture of me

Welcome, my name is Paul Stovell. I live in Brisbane and work on Octopus Deploy Octopus Deploy, an automated deployment tool for .NET applications.

Prior to founding Octopus Deploy, I worked for an investment bank in London building WPF applications, and before that I worked for Readify, an Australian .NET consulting firm. I also worked on a number of open source projects and was an active user group presenter. I was a Microsoft MVP for WPF from 2006 to 2013.

At the start of the year I wrote about how 2014 would be my year to focus on growth:

Most of 2013 was spent on building Octopus 2.0, and I think the product that we have is awesome. My goal for 2014 is to focus on growing the business, by spending 60-80% of my time on growth-oriented tasks, rather than writing code.

Octopus grew at an average of about 40% each quarter this year, which is a huge amount. We went from a two person company to seven, and we went from working at libraries to having our own office. We took an investment from Red Gate, but our growth started before then and was all funded by revenue. And on the personal front, I got married and had a baby this year, so it was busy in many ways!

My goal was to learn a lot about marketing and specifically advertising, assuming that these would be the engines of growth. I assumed it would mean sinking thousands into AdWords and banner ads, running A/B tests, optimizing, sponsorships and other "traditional" tech marketing (the kinds of tasks you'd hire a "marketing person" to do). I spent a lot of time on those activities, and we had experts to help on them too.

It turned out that none of those things really work. No one searches for deployment automation tools, it's still not an established market. Adopting something like Octopus is a journey that involves changing your practices, your processes, and changing minds on your team. No matter how many banner ads you see, they aren't going to convince you to embark on such a journey.

When I look over what worked this year, it's all the things we did before. We blog. And not in a sleazy, content marketing, click-bait way. We blog about what we're working on, and lessons we've learned along the way. We blog plans for the future, feature concepts, and problems we're having. We're active on Twitter. When suggestions come to our UserVoice site, we actually complete them (even if it takes a while).

And fundamentally, we have a pretty good product, which solves a problem important enough that people want to talk about it. At nearly every major conference this year, someone who doesn't work for us has presented on Octopus Deploy. Every week there are new blog posts. That's all down to the product and how we engage and communicate. All of those traditional tech marketing activities took away time that I could have spent making the product even better.

All in all, it has been a great year for Octopus. And while I may have wasted too much time on advertising and other activities that turned out to be a distraction, I'm glad I gave it a shot. The best part about this job is I'm learning and growing in so many new ways every day.

Providing good customer support is the most important part of running a software business. When dealing with a support queue, it's very tempting to look at the list of tickets, and to try and work your way through them by responding to as many as you can, as quickly as you can. I had an experience today that reminded me about the importance of actually solving problems vs. simply responding to tickets.

Last week, I wanted to add a new AD domain to a Windows Azure subscription. I entered the domain, tried to verify it, and got told the domain was already in use. I couldn't figure out why, so I paid $30 for a support contract so that I'd be able to contact Microsoft support.

I lodged the ticket, and a few hours later got a reply. It turned out that I had an Office 365 account which must have had the domain already linked, so I'd need to sign in and delete it from there. As far as I knew I had closed the account and was no longer paying for it, but apparently it was still open. So I spent 10 minutes trying to remember my credentials for the service, and then eventually had to reset the password.

Upon getting into the account, I tried to delete the domain. It pretended to be deleting for 15 minutes, then eventually failed. I tried again and got the same error, so I then waited until the next day and tried again. When I got the same error, I emailed my support person again, and was told it's probably because I have users using that domain.

The steps to rectify? I need to create a new user account, then delete the other users, then I might be able to delete the domain. It sounds like a lot of work, so I'll need to wait until I can set aside the time to do it.

Now, in their defence, the support person at Microsoft has been very diligent and has done a good job - they have phoned me me every day to see where I'm up to on the ticket. They send polite emails and explain the steps properly.

The fact that it's taken too long to resolve is my fault. I'm busy, and this isn't a priority issue. I just want to add a domain, and figured it would take 10 seconds to do. Between the emails and trying to delete things and trying again and searching, it's probably taken a couple of hours (not to mention the $30). And when I see the support person's # on my phone, I screen the call, because it's usually not a good time - I just haven't had time to set aside half an hour to create the accounts and delete the other accounts and do whatever else they said I'd need to do.

We provide technical support at Octopus Deploy, and it's common for some issues to take multiple emails to solve. Being on the receiving end this time has helped me to realise a few things:

  1. If you can, just solve it for them. If the support person had just logged into my accounts and deleted everything for me (perhaps with confirmation first), it would have taken 2 minutes of my time to reply to that email and the ticket would be closed. We sell shrinkwrap software, so that's hard; but this is SaaS, so it should be easy.
  2. Try to think ahead and pre-empt what could go wrong when giving a solution. I got told to delete the domains, so I tried. Only when it failed did they point out that user accounts could be using the domain. That's probably a common issue; if they'd suggested that in the first email, it would save a roundtrip.
  3. Measure response times, not issue open times. I'm getting calls and emails each day from this (very diligent) support person. I'm sure they genuinely want to help, but I suspect the follow ups are more due to the fact that this ticket is "open" and they're reminded each day to follow up. Respond to the ticket quickly, but don't follow up every day to try and get it closed - give the customer time to work through it. Chances are, this issue isn't a priority.
  4. Don't change communication mediums. I contacted support via an online ticket system. Getting a phone call was unexpected and annoying. If I phone you, sure, call me back. But if I email you, just email me back. The fact that I'm not screaming down a phone suggests I probably want to solve this using an asynchronous communication mechanism.

Observation #1 is probably the most interesting. Between the time spent on emails and phone calls just from their side, I'm sure it would have saved Microsoft a lot of money if they could simply have deleted it for me.

Our team at Octopus has grown a lot this year, and we're going to be even bigger by the end of the year. Right now there are 7 of us (5 full-time). Next week, Damian will be starting, and in addition we're also actively hiring for four more roles. Talk about busy!

When it was just me working on Octopus, I worked from home. When Nick joined, we started to meet occasionally at libraries and coffee places to work together, while also working from home most days. When we grew to 5 full time, coordinating which days to meet up was hard. So as a team, we settled on a plan of meeting up and spending the day working together every Wednesday, which creates something consistent and reliable.

But with 5+ people, working from libraries and coffee shops just doesn't work. So a few months ago we started looking for office space, and after a long search we found something we liked. We made an offer, and after what seemed like forever, our purchase finally went unconditional:

Our office

540C Queen Street, Brisbane

It's 121 square metres, so I'm hoping to get a couple of years out of it before we outgrow it.

It sounds funny to say, but despite having now committed to a physical office space, I still can't quite predict how the space is going to be used.

I still believe that people should be able to work from home if/when they want. After all, unless there are small children in the house, there's usually no place more comfortable and quieter than your own home. And if there are small children in the house, I'd encourage you to work from home anyway, because they only stay little for so long. Take time to enjoy it while you can.

What I suspect will happen is that the office will become a "resource". We'll keep meeting up as a team every Wednesday to get that face-to-face collaboration time. If two people are working on a feature, perhaps it will be easier for them to use the office than to try and find space at a coffee shop.

While I always dreamed of having the Fog Creek private office layout, that doesn't seem to be the kind of layout that would work for us. If you want a quiet space to work, just stay home and save the commute. If you're in the office, you are there to collaborate, so we need a layout that facilitates that.

The action plan at the moment is:

  1. Get the keys
  2. Do some minor work to make it usable - there's a very noisy pipe that needs fixing
  3. Add desks, chairs and monitors
  4. Try it for a month, then decide what to do next

To make pairing easier, we've gone with some large, straight desks rather than corner desks. For chairs, of course it had to be Aerons. And I have half a dozen of these 27" Dell monitors in my garage waiting until the day we can move in (everyone gets a $4,400 laptop the day they start, so we don't need to worry about anything else).

Once we've used the space for a bit, then we'll take some time to make changes. There's a wall that I suspect we'll tear down to make for a much wider open space, and then we'll add a smaller meeting room or two (for phone calls) along the side. Then I want to paint the walls with whiteboard paint to make for a lot of collaborative space.

Once we're in I'll post some pictures. Until then, I need ideas! How would you design your ideal office space? What are some cool features we could add?

Special thanks to my wife (and our CFO) Sonia, who did so much work to find the space and organise the purchase. You rock!

In Octopus, we use RavenDB as our database for almost everything. Over time, I'm noticing that we really keep two distinct sets of data in Raven, and I'm beginning to reconsider whether having one store for both of them is the best solution.

The two sets of data I'm referring to are:

  • Definitions. Environments, machines, projects, deployment steps, variables, and so on. They define what will happen when you deploy something. There usually aren't more than a couple of thousand of any of them. As a user, you spend time crafting and modifying these.
  • Records. These collections include releases, deployments, audit events, and so on. Basically, they are a record of the actions you've done using the definitions above. These collections can balloon out to many thousands, perhaps millions of documents. As a user, these are created from simple clicks or even automatically via API's/integration.

When diving in deeper, there are some other notable characteristics:

  • Simple vs. complex: The first set tend to be very complicated documents, with a lot of nesting, dictionary properties, and so on - perfect for a document database. The second set tend to be small and flat, with just a handful of fields
  • History: when you change variables or deployment steps, we take snapshots of them, so that old releases can still use the old values while new releases get the new values. This means that we keep multiple versions of the same document in Raven.
  • Retention: retention policies only really apply to the second set of collections.

The first set of documents lend themselves well to a document database, but there are so few of them that I'm not sure we do need a database behind them. The second set of documents would probably work just as well (if not better) in a relational database.

Our documents in Raven

Right now, Raven makes a good store because it is both a document database (great for our complex definition documents) and is also able to handle our record data. But it's starting to strain. A customer with 43,000 documents sent us a backup, and it took 20+ minutes to rebuild all the indexes before it was usable. Audit events work nice until we have hundreds and thousands of them; ideally we'd keep them all and not apply a retention policy, but then we have to pay to index them all the time.

Perhaps, just maybe, a hybrid storage solution might make more sense?

Tonight I spent some time prototyping a Git-based "document" store. From a C# API point of view, the goal is for it to feel just as friendly as a document database:

using (var session = store.OpenSession()) 
   session.Store(new Project("My project") { ... });
   session.Store(new Project("Another project") { ... });
   session.Commit("Added some projects");

Under the hood, it uses JSON.NET to serialize objects to JSON, and persists them on disk, followed by committing them to a local Git repository (libgit2sharp is amazing, by the way). What's exciting is that this would give our users a whole lot of benefits that come for free when using Git: viewing history, diffs, branching, merging, pushing to TFS or GitHub, and so on.

The missing feature is obviously indexing. Since these tend to be small data sets, however, I think we can probably get away with just putting everything in memory and filtering with LINQ when we need to. We could easily load a few thousand machines into a list, and keep them there until they are invalidated.

While this would work for the first set of documents I talked about, it wouldn't work for the second set. For that, I suspect we would switch to a relational database that can be embedded (probably SQLite). These records have few columns, are quite flat, and would only need to be indexed on one or two columns.

TeamCity appears to use a similar hybrid storage model, with project definitions and build configurations stored as XML files on disk, but records of individual builds stored in a database. As for Octopus, I don't know if or when we'll make the move, but it feels like a hybrid storage model that embraces the differences between the two sets of data is only going to become more compelling in the future.

In the mean time, if anyone is interested in collaborating on a Git-backed persistance solution, let me know :-)

We use RavenDB in Octopus, and one of the features Raven promotes is the idea of Safe by Default, which actually caused us a big, unsafe problem.

Safe by default

The feature in question is "Unbounded result set protection". In short, it looks like this. Say you have 10,000,000 documents of type Foo, and you do this:


The most you'll ever get back is 128 records (embedded mode), or 1024 records for an externally hosted server.

In fact, even if you do this:


In embedded mode you'll still just get 128 records.

This "feature" has hit us plenty of times in Octopus in the past - we didn't expect people to have a lot of projects, so when someone added their 129th project, you can guess what the bug report was. But overall, not too bad, and a good bug to have if you charge for support (sadly, we don't :-)).

I always considered it an annoyance, an opinionated design that goes a little too far, until today.

In Octopus we have a built-in NuGet server, and users can push NuGet packages to it. To decide whether to delete a package, we need to work out which packages are used by a given release - if the package isn't used, it is safe for deletion.

Our query was:

 var releasedVersions = await session.Query<ReleasedPackageVersionsIndex.Result, ReleasedPackageVersionsIndex>()

Today I logged in to our demo server to find the packages had all been deleted; you can spot the bug.

We've been working with Raven for many years now and even still, bugs like this creep in - it's just too easy to call ToList() without considering what might happen. Perhaps it's our own fault, or perhaps this 'safe by default' opinion goes just a little too far. In this case, it would be safer to run out of memory or crash than to delete files.

We use Tender for most of the Octopus Deploy support. I really like Tender because:

  • It allows for public (default) and private threads - we get very few duplicates because most people search for existing threads first
  • It allows customers to report and reply to issues via email

However, the admin UI for Tender, at least from my point of view, leaves a lot to be desired. Most of our customers are overseas, so new topics are usually created overnight. Each morning, we have between 15 and 20 discussions to reply to on Tender. The default Tender admin experience requires a lot of navigation to open each thread, scroll to the bottom and reply to it.

So, I built TenderSmash:


TenderSmash is an alternative UI on top of Tender, that uses the Tender API's to list pending discussions and reply to them. I did a few things to try and optimize the experience:

  • It loads all the threads and comments up front - so you can just read, reply, read, reply, without waiting between threads.
  • It shows comments in reverse order - most of the time you only need to read the most recent comment before replying
  • It uses some quick response templates to generally reduce the amount of typing required

You can play with TenderSmash here:


TenderSmash is open source - you can find the code on GitHub.

There are many dimensions to a business:

  • Product
  • Support
  • Marketing
  • Sales
  • Operations
  • Partners
  • Vision

At any given time, the business can be growing (or shrinking) along one or many of these dimensions. Early on, I thought that launching a business was all about the product. But now, I'm starting to see that the product is just one part of the business, and that no single one of these dimensions is more important than any other.

The first lesson I've learned is that whenever one of these dimensions is growing faster than the others, it can lead to pain:

  • When you've spent 6 months working on the product, without equally investing in finding and talking to customers, it will be painful
  • When you quickly gain customers but don't have a big enough team to give them great support, it can be painful
  • When you have a beautiful roadmap and vision of the future, and a backlog of features customers really want, but not enough developers to build them, it can be painful
  • When you spend all your time on marketing and promotion, but haven’t invested in a product that can meet the expectations, it's going to be painful

To avoid pain, all of these dimensions need to grow in unison. When they aren't, it looks like this:

Dimensions of the business. Numbers are arbitrary, to give you a sense.

Right now, our pain point is support. We want to give everyone a great experience with the product and to be as helpful and responsive as possible if people encounter issues. But we're growing, and so is the support load, and getting through it can easily occupy most of the day. It's not a problem that we can't overcome, but it is an example of where we haven't grown uniformly and are therefore feeling pain.

Tomorrow, I'm interviewing candidates for a support role to try to add some balance. And that's the second lesson: as I get better at this, I hope I'll be able to anticipate when one of these dimensions is going to start to lag, and to be more prepared. Ideally, I would have hired someone to help with support 3 months ago, so that by now they’d be an expert.

StartupAUS published a report highlighting some of the issues that startup founders in Australia face. It's a good read, covering the problems but also proposing a number of solutions. You can view the report as a PDF, or read a summary from Delimiter:

The report highlights a number of key issues facing Australia, including the fact that Australia’s startup sector is maturing at a slower rate than many other nations; that high-growth tech companies could contribute 4 percent of the nation’s GDP by 2033, compared to just 0.2 percent today (adding 540,000 jobs to the economy); and that in 2013, Australia invested just $4.5 per capita in Venture Capital for start-ups, compared to $120 in Israel, $85 in the US, $20 in South Korea and $15 in the UK.

One thing that surprised me from the report is just how small the startup community here is. After examining how badly we're performing, the report makes a number of recommendations about what should be done. Examples are the creation of an entrepreneur visa, changing the tax treatment of employee share options, better tax treatment for angel investors, and enabling crowd funding.

I don't think what we're doing at Octopus Deploy really counts as a "startup" in the sense described in the report, and perhaps that's why I found the report interesting, but also pretty irrelevant to us. Like most of the discussion about startups these days, it feels heavily geared towards helping would-be founders find VC funding. It's all about chasing funding.

While Australia might be a bad place to start a "startup", it's not too bad of a place to start a bootstrapped business like ours. There really is only one downside: the timezone makes it hard to offer great support to 95% of customers at times that suit them, so we have to wake up early and go to sleep late sometimes. The tyranny of distance naturally makes it difficult to connect with and influence trends in other areas of the planet.

I do have one idea though: our banks could do a lot more to provide solutions to help Australian companies process payments from overseas customers. Ideas like that are pretty irrelevant to the startup scene though, since almost by definition collecting revenue isn't something a startup will ever worry about :-)

In April 2006 I received a Microsoft MVP award for WPF. It was mainly due to some popular articles I wrote on CodeProject when WPF was brand new, and for the user group presentations I was doing. At one point, I think I managed a user group presentation every month for a year. When working at Readify, I also put together and taught a two-day WPF training course.

I kept receiving the award each year until this year, when my re-award date came and went, and I noticed I'm no longer an MVP. I guess that's fair. After all, my last post about WPF was a 18 months ago when I blogged about how nothing has improved in WPF for the last 6 years. I'm probably not the best candidate for being a WPF MVP anymore.

The BizSpark membership for Octopus Deploy is coming to an end soon too, though, so this leaves me wondering: what am I going to do when I don't have an MSDN subscription anymore? Am I supposed to pay for this stuff?! :-)

This post is part of a little series I've been writing about selling software. In this post, I want to talk about the customer experience of using resellers vs. processing orders yourself.

The Digital River experience

This morning I went to fix a bug in our Java-based TeamCity plugin, when IntelliJ IDEA (the IDE that I use) told me that my trial license had expired. I like JetBrains, and I like their products, so I went ahead and bought a license.

After entering my details, I was taken to a payment page, where I was told my payment would be processed by Element 5:

My payment will be processed by Element 5

After placing the order, I got a receipt via email. Except instead of seeing Element 5, like I expected, it said MyCommerce, with "Thank you for placing an order with MyCommerce, an authorized reseller of JetBrains s.r.o...":

Apparently I actually purchased from MyCommerce

There was an invoice attached to the email, though, and it said Element 5, not My Commerce, and it had Digital River underneath. Confused? So am I. There are so many brands and logos involved in my order that I'm left feeling pretty unsure about who I actually gave my credit card to.

The invoice from Digital River and Element 5

Now, I understand that Digital River is a large company that has a number of different brands that they use to process e-commerce payments (and I suspect that they rename these companies often because they develop not-so-positive reputations). But to me, this lack of attention and confusion about brand identity comes across as very amateurish.

I was in a hurry to get my bug fixed. So I scrolled down to find my license key in the email:

Your product will be delivered in 24 hours

At first I assumed the 24 hours was just a standard disclaimer, but as time went by and no license key came, I realized they were serious.

My license key arrived 5 and a half hours later

Eventually, 5 hours later, my license arrived. I’m not sure why it took so long to email a license key. Perhaps their license algorithm relies on the unique entropy of Hadi Hariri doing the hammerdance? Who knows.

Having to wait for something that should be automated was disappointing. But that confusing invoice from a company suffering an identity crisis did not leave me feeling like JetBrains particularly care about how I felt.

Now, the point of this post isn't to bash JetBrains (I really love their products!) or even Digital River. This experience just reminded me of why I moved away from using resellers.

While outsourcing to resellers might be attractive, and might even make commercial sense, the downside is is that you no longer own the customer experience. JetBrains have earned my trust with their brilliant products, and they have a nice website that explains the features in detail and convinces me to buy. But the buying experience was impersonal, confusing and disappointing.

How I used to do it: FastSpring

For Octopus Deploy, I previously outsourced order processing to SWREG (another Digital River company), and then quickly moved to FastSpring. I wrote about how I take orders with FastSpring previously.

But in December I made a change, and decided to process the orders myself. I figured it would allow me to save a few thousand dollars a month in processing fees. And it would make reconciling with my accounting system easier too. But the real driving force behind deciding to process orders myself?

I wanted to own the customer experience.

I hated that FastSpring couldn’t actually create quotes and I had to issue them myself on their behalf (since the order will ultimately be paid to them). I hated that FastSpring’s invoices couldn't be turned into PDF's very nicely, since many customers ask for PDF invoices (the invoice email just linked to a web page with details). I hated that while my store was branded to look like my site, the invoice had FastSpring's color scheme and logo, and couldn't be branded. I hated that when large customers asked for extra documentation or tax forms, I had to send them off to someone else, because I wasn’t actually the merchant of record for the transaction.

Now, FastSpring were great, and their support really is as good as they say. And I think at the time, they were the right choice: I didn't even know if anyone would buy my product back then, let alone have the time to implement order processing myself. And I'd recommend them to anyone else who is launching a product. But after 12 months with them, I decided it was time to grow up and begin to own the customer experience.

Current strategy

In December I launched an update to the Octopus Deploy website, and implemented a new order processing system. It is built using ASP.NET MVC and RavenDB, and hosted on EC2. It took about a week of work, but deploying it was easy :)

In our system, quotes, purchase orders and orders are all effectively the same thing:

  • A Quote is a request for pricing that doesn't represent a commitment to buy
  • A Purchase Order is a commitment to buy, that hasn't yet been paid
  • An Order has been paid

For payment methods, we accept Visa/Mastercard (through a merchant facility with NAB, and the Braintree gateway), or PayPal. PayPal also lets customers pay with credit card without registering, so we use that for AMEX and other cards.

Customers can come to the site and buy right away, or they can request a quote, turn it into a purchase order, and then eventually pay it. Here's how the order process looks at a high level (click to zoom):

Order processing system

When a customer requests a quote or places an order, a background task sends the quote/invoice to Xero, using the Xero API. We then download that invoice as a PDF, and it gets attached to the outgoing invoice email.

We use three different invoice templates in Xero because quotes, purchase orders and paid orders all look a little different. Click below to see examples:



Purchase order:

Purchase order, unpaid

Paid order:

Invoice, fully paid

The license key is also generated and sent immediately via email. But there’s more.

After purchasing/placing the order, if you stay on the confirmation page, the page will eventually refresh and show you your license key and invoice as a PDF. You don’t even need to check your email. It’s right there. We generate them in the background while you wait, but usually it’s just a few seconds.

We give you the license key immediately

What I love about doing it ourselves

Firstly, I love that our invoices and license key emails all come immediately, and that they come from us, with our logos and no third parties. It feels clean and professional. And I love that customers don’t even actually have to wait for the email to get on with things.

Processing the payments ourselves is also great for cash-flow. With a reseller like FastSpring, we could only get paid fortnightly at the most. With our own merchant account, a customer can buy today, and the funds are cleared and ready to be spent tomorrow. And did I mention we’re saving a lot of money in transaction fees? (FastSpring was 5.9%, while accepting cards ourselves is 2-3%)

Finally, I love that everything pretty much reconciles itself. In Xero, as soon as a customer places a purchase order or pays an invoice, I can see it in my profit and loss statement. A few days later when I import the transactions, I tick some boxes and the reconcile is done. Our accounting system IS the invoicing system. Reconciling accounting with FastSpring and SWREG was much harder.

The downside

The one downside to not using a reseller is that actually accepting payments is harder.

FastSpring allowed us to fix prices in a dozen different currencies, accept pretty much any credit card, and even accept checks or bank transfers as payment methods (our US customers could mail a check to FastSpring, they’d clear it, and a few days later the order gets marked as paid).

Now that we’re doing it ourselves, we’re a lot more limited. To price in different currencies you have to actually have a bank account and merchant facility in that currency (currently in Australia, only NAB can provide this). We price our product in USD, so we have a NAB multi-currency facility and a USD bank account. We can’t accept AMEX in USD because AMEX are, frankly, idiots. We have to send customers to PayPal to use their AMEX cards.

And since our bank accounts are in Australia, it’s really hard for customers overseas to pay by bank transfer. It took about 7 emails for one of our customers in France to be able to pay us via bank transfer, and we lost about $50 in processing fees by the time it arrived.

So far, though, limiting the payment methods hasn’t actually been that bad - sales have been growing despite reducing the payment options, and I’m getting emails occasionally from people about how they enjoyed the purchasing experience, which we never got with resellers before.

Is it worth it?

If a small company like ours can do it, why haven’t a 300+ person company like JetBrains done it? Your Octopus Deploy license will be ready within seconds of ordering, yet it’s been 6 hours since I ordered my IntelliJ IDEA license and I am still waiting. They have 300 employees, we have four.

When it comes to outsourcing, it’s always recommended to outsource your non-key competencies. And while processing payments might not be my core competency, I think it’s so essential for the customer experience. Purchasing is the last part of your sales funnel, and it’s too important to be left to the Digital Rivers of the world if you can help it.

Update: Sounds like JetBrains might be making some changes