Yesterday, September 8th, it was 10 years ago we released the first LLBLGen Pro version, v1.0.2003.1 (see the blog post about that release). To celebrate this, we give everyone 10% discount when purchasing one or more licenses in the coming 10 days, till September 17th, 2013! To get the discount, use the coupon code 10YEARS on the order form.
A brief history…
In early 2002, I released a small tool named LLBLGen, which generated SQL Server stored procedures for basic CRUD operations and code in C# and VB.NET to call these procedures. .NET was new, Visual Studio.NET was new, tooling was simply not there and LLBLGen was something many people needed. I released it with the source code so people could make adjustments and it was downloaded at least over 50,000 times (but I lost track along the way). Due to this success and the constant stream of requests to add more features, I decided to create a commercial version of it: a designer which allowed people to design their stored procedure code, combined with a code generator. Development started late 2002 and Solutions Design, my company, had funds for 7 or so months of work.
Stored procedures… not really
Several things happened during the first four months of 2003. I started to realize that the best DSL to describe stored procedures with was in fact SQL, something I wanted to generate from another specification. Another thing I started to realize was that what I really wanted to do was to work with an abstract entity model at the NIAM/ORM level and stored procedures were simply a reflection of what was required to do with instances of model elements, not a reflection of the model itself. Users of stored procedures were more interested in sets they could obtain from the database than working with entity instances.
In short: I ran into a wall which was miles high and still I hadn't seen it coming…
Object Relational Mapping
I had to make a decision: go the route I started with, which I had the feeling would lead to nowhere, or go the route I actually wanted to go, which had the consequence I had done a lot of work for nothing. I decided to choose the latter: throw away what was useless now and build a system which would meet my goals: a system which allowed people to work with the instances of an abstract entity model in their code.
Oh, and I had 3.5 months to do it, as funding was running out…
LLBLGen Pro v1.0.2003.1
I worked many hours a day, 6-7 days a week, no time for anything else. Object Relational Mapping was defined pretty clearly by Scott Ambler's paper however I didn't want to use POCOs: POCOs required sub-classing/proxies and the tools to create these objects on the fly were not mature enough at that time, plus I wanted to be able to create new entity class instances using the new C#/VB.NET operator, without the requirement for the developer to use factories. I designed a DTO based system using field objects. The DTOs were arrays of field objects which were passed to the engine for SQL generation and object materialization over result sets. The field objects were typed, so I could use them to formulate queries in code without strings: queries were type checked which was a huge step forward compared to the rest of the systems available at that time (read: none).
In July 2003 I was done developing what I thought would be v1.0. From the group of users of the free LLBLGen I chose my beta-testers and worked with them to get v1.0 out the door. Funding was a problem though: with no income coming in, there was a hard limit on how long release could be postponed. Luckily my wife (with whom I run Solutions Design) registered some domain names back in the day when 'The Internet' was something the majority of humans considered to originate from out of space and was brought to us by aliens in black T-shirts and long hair. Around that moment some guy purchased the domain names from us so we had some new funding. That is, till the end of September. If 'LLBLGen Pro', as we named it, wasn't a success, we would be in serious trouble.
We picked 'LLBLGen Pro' because the free 'LLBLGen' tool was so widely known, it would be foolish not to, even though pronouncing it was a bit of a …. problem.
After working almost non-stop and barely sleeping for a month, we managed to get v1.0.2003.1, our first version, including a manual, examples, a website, a system to let customers purchase licenses etc. ready to launch. Late that 8th of September 2003, I think around 10:30pm, we flipped the switch and the site, the first version and everything we worked so hard for, was live. We didn't have any budget for ads, so we used my blog to announce its release, usenet newsgroups and some forums to get the word out.
Within 8 minutes we had our first customer. When that first email arrived with the customer information, I knew… the choice I made all those months before was the right one. We used a common, proven, sales tactic: get a large amount of people to use your products first, the financial success will come after that. So we started with licenses per-department: 1 license purchased was usable by everyone in a department. This made us a very inexpensive alternative to money hungry competitors like Firestar (which had a competing product costing many thousands of dollars. Firestar is that company that later on sued Red Hat over Hibernate's ORM patent infringement)
New versions, new features
With the sales of v1.0.2003.1 I could fund further development of newer versions, newer paradigms, extensions on the runtime, the designer, the code generator, create a better website, add a support forum, write more docs and examples and much more. Due to the limited time I had to build v1.0.2003.1, a lot of features were still not there.
One comment on that blog post 10 years ago I'll never forget:
How will you make money selling it so cheaply? I would think that support alone would kill you.
With the pressure to add new features to stay ahead of the competitors and the increasing amount of support requests, that comment hit me almost every day after a while: I had to do something or LLBLGen Pro would die due to its own success. The solution was to hire a support team. This team, which consists of 2-3 people working on freelance basis, started to do support for us and I could continue working on new features and versions. Of course bug-fixing was still my problem, but at least I could focus on new stuff, instead of more and more getting swamped with support requests. All support team members are and were customers once, they knew the tool well enough to get started without training.
I think we were lucky that the support team members we hired were and still are excellent and indirectly enabled us to get through the years by building new features and release new versions. Thanks Walaa and David, you're the best!
Today and onwards to the future…
After 10 years we still work on LLBLGen Pro every day full time and sales still allow us every day to do that without external funding. In the past 10 years we have seen many competitors come and go, and it's a sign of our solid product that from all the competitors we had back in 2003-4 no-one is still in the data-access business: they either went bankrupt or transferred into a consultancy firm.
We added a second product, ORM Profiler (which v1.5 beta was released 2 days ago), to our portfolio and while profilers aren't tools which will make you rich, it's a tool which in our eyes extends the vision we had all those years ago: create tools which allow the developer to work easily with abstract entity models in an application.
In the LLBLGen Pro universe there are still a lot of things to explore and to add to the system, so I'm not done yet, not by far. Some people ask me sometimes whether it doesn't get boring to work on the same code every day. Sure, like it does in any project. The fun part is however that it's my code base, I designed it, I wrote it, have seen it come to life and make it do what I had in mind. So while sometimes work can get boring, it is still work done on what I believe in. Additionally, the system consists of various parts which individually are very interesting and diverse: query engines, a runtime, a designer which allows modeling of abstract entity models, code generator engines etc. etc. One day you're working on undo/redo logic of a graph of objects in-memory, the next day you're working on query transformations from one DSL to another, or trying to find a way to optimize a bottleneck in the object materialization pipeline. There's always an interesting part to work on next.
What the next 10 years will bring, I have no idea, but I do hope I can continue what we've started all those years ago. Thank you all out there who have supported us through the years and onwards, for making it possible that I can look back at 10 successful years and look forward to many more to come in the future!