OdeToCode IC Logo

Travelogue - The Pluralsight IPO

Wednesday, May 22, 2019 by K. Scott Allen

I have a difficult time stating that I left London early to reach New York City in time for a pre-IPO party without laughing at the gaudiness of it all. However, that’s what I did just over one year ago.

My Pluralsight story begins at a Visual Studio Live! Conference in 2007 when I met Fritz Onion in a speaker’s prep room. Fritz knew me from writing and blogging, and, eventually, our first meeting led me doing a "test teach" for Pluralsight.

A "test teach" is a short tryout involving real students, but it was more than just a check on my speaking ability. I believe the "test teach" evaluated several soft attributes. Could I build a rapport with the students? Do I handle questions well? Can I socialize at lunchtime? Can I successfully arrange and coordinate travel on my own to reach the customer? It’s one thing to plan a trip to visit a tourist attraction where signs and strangers would help you along the way. Planning a trip to arrive at a nondescript office building in a generic business park of Jersey City at a very specific time requires more expertise [1].

The test teach went well, and now I'm on a plane into Newark. Over the last 10 years I've taught dozens and dozens of classes all around the world for Pluralsight. I've made over 50 video courses for Pluralsight.com. The company is ready to go public, and I've been invited to the opening bell ceremony!

The Arrival

I’ve never been on a car ride into the city. I’ve always arrived on a plane, or underground on a train. But on this trip, I arranged for a driver to take me from Newark Airport to the W hotel in Times Square. It was my first time in a car through the Holland tunnel, and with all the traffic into the city at 7 pm, I had plenty of time to study the tunnel. The night was dark, wet, and foggy. New York had put on its Gotham city look, and I was waiting for the Batmobile to zoom past using an invisible traffic lane.

Arriving in Gotham

The pre-IPO dinner party was at Estiatorio Milos, a Greek seafood restaurant on 55th street. Milo’s food was okay. The place had the feel of an upscale restaurant designed to extract as much coin as possible from patrons while giving those same patrons the ability to brag to everyone about eating fish flown in fresh from the Mediterranean. Form over function. The company and festive atmosphere were better than the food. I joined late but found a seat among other authors, including Joe Eames, Deborah Kurata, and John Sonmez. Although there was talk of an after-party involving an ultimate milkshake, being on UK time, I needed sleep before the big morning.

Milo's Food Offering


Times Square in New York is an astounding place. Bright lights, tall buildings, and a mass of humanity moving through the streets. The ads are so intense they lead to sensory overload. There are animated ads for movies, which want to take your money in exchange for laughs. A four-story jewelry ad wants you to trade money for diamonds. Underwear, outerwear, phones, hotels, and banks all project images in a quest for branding and customers.

Times Square from a Distance

There was a time when I would have dismissed the square as being too artificial. But, after reading A Splendid Exchange, I’m seeing Times Square as a primal center of trade, and a natural expression of what humans have been doing for centuries. It is the place where humans come to make exchanges.

The Peak of Civilization

When we leave the hotel the morning of the IPO, the exchange we are looking for is the NASDAQ exchange on 4 Times Square. The NASDAQ is hard to miss thanks to the 7-story curved LED display outside. In fact, this NASDAQ location is really more of a media center than an exchange. The place has television studios inside, and rooms with hundreds of cameras where companies doing an IPO can ring the opening bell and look like they are on the trading floor surrounded by “traders” working diligently in front of computer monitors. The physical NASDAQ trading market exists only in silicon and fiber optics.

I’m one of only six or so authors who’ve been invited to be present for the IPO. There is also 50 or more Pluralsight employees, board members, and investors. A few of the people I’ve known for years and grown fond of. But with Pluralsight’s rapid growth, the majority are strangers to me. Nevertheless, we are bonding together like molecules in a high-energy physics experiment. I’m barely through the security entrance when Gene Simmons walks out of a TV studiio. He saunters over to 4 of us gawkers and in a Gene voice says, "So ... what are you gentlemen here to sell today?"

Me and Gene Simmons

You’ve never felt like a true nerd until you tell Gene Simmons about your training videos covering software development. It is impossible to perform this task without sounding like the D&D dungeon master at the corner table of a comic book store.

It Happens Quickly

During an IPO, there are two significant moments. The first moment is the opening bell ceremony. Not every company will choose to participate in the ceremony, but I'm glad Pluralsight did. For this ceremony, everyone gathers on the stage in a circular room. In the room there are dozens of electronic displays hanging from the wall, and even more cameras. The cameras cover every possible vantage point on the stage. There’s a podium on the stage, and NASDAQ people walking around wearing headsets, carrying clipboards, and giving orders with all the authority of a television producer. In the moments leading up to the 9:30 am market opening, they are giving us pep talks and telling us the more we clap and yell, the better we'll look on TV. I'm a bit worried that if we manage to add more energy to the room, we will start a chemical reaction that lays waste to the entire building.

The NASDAQ Media Room

At 9:30 am, the person at the podium (Aaron, in this case), takes a cue, pushes a button, and the bell rings. Confetti begins to fall. There’s yelling, clapping, and arm raising. I think of my parents. I wish they were still alive to see this moment. I’m one parental memory away from losing it and crying all over the stage. I can’t ever remember euphoria and sadness being mixed like this.

After the opening, there is professional picture taking, both inside the building, and outside in Times Square. There's also champagne, and singing and laughing, and selfies. Lots of selfies.

Ring the Bell!

The next big moment on IPO day comes when the first share of stock is publicly traded. I don’t remember the precise moment when this happened, but I think it was about an hour or 90 minutes later. There’s a roar when the price of the first trade execution hits the screens. There’s hugging, handshakes, and back-slapping. More selfies, lots of selfies.

First Trade Executed!

And then ... dispersion.

We leave the studios and head back to the hotel. Most Pluralsight employees are flying out in the afternoon to be back in Utah the same day. I’m beginning to think that if my driver can come early, I’ll get through the tunnel before rush hour hits and catch an earlier flight home. Flights between D.C. and Newark go once an hour when the schedules are working. If I can't catch an earlier flight, maybe I'll take the train. Either way, it’s not even lunchtime and I’m exhausted.

In the end, I did catch an early flight. However, before I left, I had a quiet celebration with a meal worthy of a billion-dollar IPO. I had a $5 hot pastrami sandwich from a street vendor two blocks from Times Square.

Function over form.

[1] Years ago, a renowned training company approached me about teaching a Web API class at Microsoft. For my first class, I was given a location on the Microsoft campus and told a Microsoft employee would be there to let me in the classroom. I arrived 30 minutes early and began waiting for my Microsoft escort to arrive. With 15 minutes left before the class started, I started emailing and trying to reach people at the training company to let them know my escort wasn't arriving. The classroom was in a locked down section of the building, and I wasn't getting past the entrance without my escort.

Finally, as my escort arrived 2 minutes before the class began, I entered the room in a state of panic. As I was setting up, I noticed that one of the well known instructors from the training company was sitting in the front row of the class. He was directly in front of my podium, and I heard him say, into his phone, "looks like he finally made it." I didn’t have time to think much of the statement at the time, as I only wanted to get plugged in and take a couple of deep breaths before launching into an all-day technical workshop for 70 MS engineers.

Later, when I replayed the opening events in my mind, I was furious. Why didn’t someone let me know he’d be there? Why did no one respond to my calls? Why couldn’t he provide me with an escort? After that experience, I think I finished one or two more classes for this training company that we had already arranged, and then I let the relationship expire quietly.

I tell this story because Pluralsight has always treated me with respect, and that's one reason I've been loyal and stuck with them.

.NET Core Opinion 13 - Commit Your Scripts

Monday, April 22, 2019 by K. Scott Allen

In a previous post, I suggested you think of your ASP.NET Core application as a command line tool you can use to execute application specific tasks. In an even earlier post, I suggested you keep scripts related to development checked into source control. I think you can see now how these two posts work together to make everyday development tasks automated and easy.

The command line renaissance gives us a wide range of tools we can use to speed up .NET Core development. Here are some of the tools I've been using recently, in no particular order:

  1. Various dotnet global tools, including dotnet-cake, dotnet-t4, and dotnet-rimraf

  2. The Windows Subsystem for Linux, because it opens up an entire universe of standard tools, like Curl

  3. The Chocolatey package manager

  4. mssql-cli

mssql-cli autocomplete

  1. Azure CLI and aws-shell


Interview on CloudSkills.fm

Thursday, April 18, 2019 by K. Scott Allen

CloudSkills.fm podcast

There's a new episode of the CLoudSkills.fm podcast available, and the episode features yours truly!

In this episode I talk with Scott Allen about building and running applications in the Azure cloud. Scott is a legendary software developer, conference speaker, trainer, and Pluralsight author.

I hope you enjoy the show.

Load Testing on the Web with K6

Wednesday, April 17, 2019 by K. Scott Allen

There are hundreds of performance testing tools for the web. The tool I’ve been using the most for the last 10 years is a part of the web test tools in Visual Studio. Microsoft officially deprecated these tools with the 2019 release. The deprecation is not surprising given how Microsoft has not updated the tools in 10 years. While the rest of the world has moved web testing to open standards like JSON, HAR files, and interoperability with developer tools in modern browsers, the VS test tools still use ActiveX controls, and require Internet Explorer.

Steve Smith recently asked VS Users what tool they plan on using in the future.

Which tool to use?

In the replies, a few people mentioned a tool I’ve been experimenting with named K6.

You can install K6 locally, or run K6 from a container. The documentation covers both scenarios. In addition to the docs, I’ve also been reading the Go source code for K6. I’ve had a fascination with large Go codebases recently, although I think I’m ready to try another new language now, perhaps Rust or Scala.

Authoring Tests

There were a few features of the Visual Studio test tools that made the tools useful and easy. One feature was the test recorder. The test recorder was an ActiveX control that could record all the HTTP traffic leaving the browser and store the results into an XML file. The recorder made it easy to create tests because I only needed to launch IE and then work with an application as a normal user. Although XML isn’t in fashion these days, the XML format was easy to modify both manually and programmatically. The tools also offered several extensibility points you could hook with C# for pre and post modifications of each request.

K6 also makes test creation an easy task. Any browser that can export a HAR (HTTP archive) file can record test input for K6, and the developer tools of all modern browsers export HAR.

Save As HAR

You can modify the JSON HAR file by hand, or programmatically. You can also use K6 to convert the HAR file into an ES2015 module full of JavaScript code.

Converting HAR to JS

Here is what the generated code looks like.

group("page_2 - ", function() {
    let req, res;
	req = [{
		"method": "get",
		"url": "https://odetocode.com/blogs/scott/archive/2019/04/04/on-the-design-of-app-launchers.aspx",
		"params": {
			"cookies": {
				".ASPXAUTH": "73..."
			"headers": {
				"Host": "odetocode.com",
				"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0",
				"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
				"...": "..."
		"...": "..."
    res = http.batch(req);


There is an entire API available in K6 with extensibility points for cross cutting concerns. With a script in hand, you can now run load tests from k6.

Running a load test

The above run was with a single VU – a single virtual user, but you can add more users and run k6 in a cluster, or in the cloud. In short, K6 has all the features of Visual Studio Load Tests, although with no UI tools for beginners. However, the APIs and command line are easy to use and rely on standard tools and languages. The current Azure load test offerings require either a web test from Visual Studio, or, a single URL for a simple test. Until this Azure story improves to add more sophisticated test inputs, K6 is a tool to keep in the toolbelt.

On the Design of App Launchers

Thursday, April 4, 2019 by K. Scott Allen

Every so often I like to wander into user experience design meetings and voice my opinion. I do this partly because I want to fight the specialization sickness that hobbles our industry. I believe anyone who builds software that comes anywhere close to the user interface should know something about UX design.

When it comes to UX, I follow T.S Eliot’s philosophy that good poets borrow, great poets steal. I’m not a good poet or a good UX designer, but I know what I like when I read poetry, and I know what works for me when I use software. I’ll borrow as many ideas as I can. In UX, there’s time for a hundred indecisions, and for a hundred visions and revisions, before the taking of a toast and tea.

I’ve been looking specifically at navigation for platforms that compose themselves from multiple applications. Applications might not be the right word to use, but think about platforms like Office 365, Salesforce, and Google’s GSuite. These are platforms where users move between different contexts. You are reading email, then you are working in a shared document, then you are reviewing a spreadsheet, then video chatting with a coworker.

All these platforms use the 9-dot app launcher icon to jump from one context to another. For example, here’s Office 365.

Office 365 App Launcher

There’s a few guiding principles we might borrow from O365 at first glance.

  1. Every navigation entry consists of an icon and text.
  2. Every icon is a bespoke icon.
  3. Every area of the platform has a brand name (Outlook, Word, PowerPoint).

However, look closely and you’ll see not every entry follows the guidelines. The outliers here are Calendar and People. Long time users of Outlook would know you can access your contacts and calendar without leaving Outlook, but on the web, Microsoft felt it was necessary to highlight these features of the platform from the highest-level navigation menu. The icons for People and Calendar stand out because the graphics are simple and schematic. The text for these entries stands out because the text is not a product name, but a friendly description of the feature you want to use.

Anyone who has ever created content for Microsoft will know how serious Microsoft can be when it comes to product names. I can imagine a war starting inside the company when someone proposed adding People and Calendar to the menu. On one side there are members of the Office team who have promoted the Outlook brand for decades. On the other side are people fighting for the discoverability and usability of the O365 platform.

Knowing Microsoft, the final decision relied on user experience testing, and I’m guessing the tests showed some non-trivial number of users couldn’t find their contacts or a calendar in the O365 UI.

I think software companies tend to overestimate the brand name recognition of their software, particularly when it comes to product suites and platforms with a variety of brands inside. All the pet names are confusing. Many users don’t care to dig into the details of 5 different product offerings. I assert this fact based on anecdotal evidence, like the following thread about the game show Who Wants to be a Millionaire?

Office on Who Wants to be a Millionaire

That’s Microsoft. What can we borrow from Google?

G Suite App Launcher

Again, we have the app launcher icon, and a navigation menu with icons and text. The icons are representative, simple, and contain only a touch of shading and nuance. The few brand names that jump out are Gmail, Drive, and the notorious Google+. Most of the entries consist of simple text and icon pairs that work in concert to provide clues about a feature area. For example, the @ icon for Chat suggests a text chat. The camera icon for Meeting suggests a video conference.

What about LinkedIn?

LinkedIn App Launcher

Once again, we see an app launcher opening a collection of icon and text pairs. However, there’s something ... uninspiring about the LinkedIn UI. The monochrome look gives a washed out appearance. There are no distinctive colors to scan for when trying to locate a familiar feature. Each entry is smaller than the entries in O365 and G Suite, and the menu appears unbalanced with the amount of white space it uses. And what are those icons? Groups and Insights are too similar, and the salary icon (an eight-sided nut laying on two sheets of paper?) is too abstract and appears out of focus - an impressive effect for a 40-pixel icon built with SVG.

My criticism of the icons isn’t based solely on some inner sense of aesthetics. There is research from the Nielson Norman Group on icon usability which says icons should be simple, memorable and recognizable. There’s also the basic design heuristics that we should have users rely on recognition, not recall, and that a system should use words and phrases familiar to the user rather than system oriented terms (like abstract product names).

In the end you can borrow ideas from multiple platforms and usability studies to guide the design of an app launcher that works best for your system. Just remember that schematic, recognizable icons and user-friendly text make the most effective launcher.

New Pluralsight Play by Play Featuring Visual Studio Live Share

Tuesday, April 2, 2019 by K. Scott Allen

Everyone should try Visual Studio Live Share. I only had to try the tool once to realize that any other screen sharing and meeting software was not going to be as good as VS Live Share (which works in VS Code, too).

Brice Wilson and I put together a Pluralsight Play by Play on Visual Studio to coincide with today’s launch of Visual Studio 2019. It’s a quick video with loads of demos, including how to use shared terminals and cooperative debugging of both C# and Node JS programs.

Play by Play Preparation

I hope you enjoy it, and the next time you want to work on a piece of code with other developers, try VS Live Share!

.NET Core Opinion 12 – Use Your ASP.NET Core App as an Executable

Wednesday, March 27, 2019 by K. Scott Allen

There is a special moment of time in the life of every ASP.NET Core process when the application has all the services registered and all the configuration sources in place, but has not yet started to listen for HTTP messages. This is a moment in time you can seize and use to your advantage.

I tell people to think of their ASP.NET Core application as a console application that happens to listen for network connections, because there are many useful tasks the application can perform at development time and in production. Examples would be tasks like migrating database schemas, clearing a distributed cache, and creating storage containers.

public static void Main(string[] args)
    var host = CreateWebHostBuilder(args).Build();

    // the moment in time when magic can happen
    ProcessCommands(args, host);


Let’s drill into database migrations. Many people will say we need to keep automatic migrations out of web applications because the results in a server farm are unpredictable. Good advice! I’m not suggesting you implicitly run migrations as a side-effect of the first HTTP request. I’m promoting the use of the application to explicitly run migrations when the app receives the right command line parameter. Think of the parameter as an automation point, and you can now migrate a database from a deployment script, or from a development shell.

Another objection is how executing utility tasks in the application feels like a violation of the single responsibility principle at the application level. Why not build a separate console application to execute utility tasks and leave the main app for processing web requests? This is possible, but you’ll find yourself needing to reuse or duplicate configuration code from the web application. Using database migrations as a concrete example again, there is a lot of work that goes into building the right services and configuration for a specific environment, including non-trivial steps like connection string decryption and network communication with key storage services. The app, assuming it works, is setup perfectly to have everything in place for a specific environment like production, staging, or development.

Here’s another example of something I’ve done in the past. On this project I could run the following command to drop the development database, recreate the database using migrations, seed the database with data, and then exit instead of entering into web server mode.

dotnet run  dropdb migratedb seeddb stop

The overall theme here is not about database specific tasks, but about automating common tasks to make development, testing, and deployments faster and more repeatable. The perfect tool for these jobs might just be the application you are already have!