Hopefully this will create a new wave off innovation, and someone will create something to replace the monopoly on IaC that IBM now owns.
Hopefully this will create a new wave off innovation, and someone will create something to replace the monopoly on IaC that IBM now owns.
Sadly I echo your sentiment about the future, as someone who has heard second-hand about the quality of work at modern Redhat.
I am wondering how many more rounds of consolidation are left until there is no more space to innovate and we only have ossified rent-seeking entities in the IT space.
This is not a pay day for many people. Anybody who got a pay day were those that could liquidate in the IPO.
Smaller and bigger percentages will be different but that's retirement money for hundreds and hundreds unless you pretend to live in very high CoL area. Also, most of them will likely have to keep working thereyears before cashing out some other millions likely.
There are many many people who made a loss on this, even before the acquisition announcement.
Also I think your ownership % is way off. There's a pretty small group of people, most of them the earliest employees + execs, who would have got out with $10M. HashiCorp currently has thousands of employees and would have churned through thousands more over the years.
IPO price was $35.
IPO day and you get 1000 RSUs unlocked/vested. Share price is $80. You made 80k gains. For simplicity let's say you owed 40K in taxes.
One of two things happens:
- Hasihcorp auto sells to cover and you get 500 less shares. - You need to pay your taxes on your own and earmark 40K.
Let's pick the easy one: If Hashicorp sold for you that day you are now sitting on 500 shares with a cost basis of $80.
Let's go to today, IBM buys and the person held. 500 shares are now were $35 so the value is $17,500.
You cash out -- getting 17,500 in your account, and a capital loss of $22,500.
Sure, 17K isn't as cool as 40K, but the person still "made money" just _less_. You make it sound like this person is now "underwater" because they had a capital loss.
=====
And kids at home, this is why you sell some/all of your RSUs as you get them. No one company should be more than 15% of your portfolio. Even the one you work at.
_A lot_ of people ended up with a loss.
The problem occurs when 22% isn’t enough, which is often the case.
People got RSUs. They owed tax on said RSUs. The tax cannot be higher than the value of the RSU at the time of vest.
If people did not have enough cash to pay their tax bill, and did not sell enough RSUs to get cash to pay said tax bill, then yes, I can see those people "with a loss" because they had a "surprise" tax bill, RSUs price went down and a cash problem now. Is this what you mean happened?
They shouldn't have had to "sell everything" -- at most like 50%.
I'm arguing with you here because this stuff is complex, and many people shy away from trying to understand it, and that's a huge disservice for those in our industry.
For anyone reading along -- It's as simple as this: understand the tax implications of the assets you own, pay your taxes.
In Australia we were granted options, which ordinarily are taxed at time of exercise. Lots of people were surprised to discover, almost a full year after the IPO, that those options were also subject to a tax deferral scheme and any tax already paid at exercise wasn't sufficient. The actual taxable amount determined by HashiCorp and the ATO was the $80 IPO price. If you sold the full amount you were entitled to (10% of your vested holdings) at the IPO you were probably fine. If you sold nothing, because you thought you had already paid the required taxes, by the time you received the tax statement the value of your stock would have been less than what you owed in taxes.
> No one company should be more than 15% of your portfolio. Even the one you work at.
Tell that to the guy who went all-in for NVidia employee share purchase plan and is worth more than 50M USD. (I think it was a Register article posted here recently.) Sometimes the gamble is worth it. That said, for every one of those once-in-a-lifetime stories, there are many, many more about engineers who walked away from post-IPO start-ups with very little wealth gained. So many have posted here before, it just isn't worth it.... Barely any employees could have that much stock. There's 2200 employees from the most recent data I see. Even if the outstanding shares were 100% employee owned, a uniform allocation would at best see a 0.045% between them all. Obviously, the shares are not uniformly distributed across employees, nor is hashicorp 100% employee owned.
First of all your percentage of ownership is unrealistic. I joined in November 2019 and got a grant of a few thousand RSUs that fully vested before I left, and that I still have most of, plus I bought some shares in a few rounds of our ESPP when that became available -- as of today I have just under 5,000 shares. HashiCorp has nearly 200 million shares issued, so I own a hair over .0025% of the company. Really early employees got relatively big blocks of options but nobody I knew well there, even employees there long enough to be in that category (and there were very few of them still around by December 2021), was looking at "fuck-you money" just from the IPO.
Second, the current price isn't the whole story for employees. I had RSUs because of when I joined so the story might have been different for earlier employees who had options, but I don't think it differs in ways that matter for this discussion. As background for others:
* On IPO day in December 2021, 10% of our vested RSUs were "unlocked" -- a bit of an unusual deal where we could sell those shares immediately (or at any later time). Note "vested" there -- if you had joined the day before the IPO and not vested any RSUs yet, nothing unlocked for you. (Most of the time, as I understand it, you don't have any unlocked shares as an employee when your company IPOs -- you get to watch the stock price do whatever it does, usually go down a lot, for six months to a year.) * At a later date, if some criteria were met (which were both a report of quarterly earnings coming out and some specific financial metrics I forget), an additional tranche of vested shares (I think an additional 15%) unlocked -- I believe this was targeted at June 2022 and did happen on schedule. * After 1 year, everything vested unlocked.
At the moment of the IPO the price was $80, but it initially climbed into the $90's pretty fast. At one point, during intraday trading, it actually (very briefly) broke just above $100.
So, if you were aware ahead of time that the normal trajectory of stock post-IPO is down, and if you put in the right kind and size of limit orders, and if you were lucky enough to not overestimate the limit and end up not selling anything at all, then you could sell enough shares while it was up to cover the taxes on all of it and potentially make a little money over that. I was that lucky, and managed to hit all of those conditions while selling almost all of my unlocked shares (I even managed to sell a small block of shares at $100), plus my entire first post-IPO vesting block, and ended up with enough to cover the taxes on the whole ball of already-vested shares, plus a few grand left over. Since then, I haven't sold any shares except for what was automatically sold at each of my RSU vesting events.
For RSUs not yet vested at the IPO, the IPO price didn't matter because they sold a tranche of each new vesting block at market price to cover the taxes on them when they vested -- you could end up owing additional taxes but only, as I understand it, if the share price rose between vesting and sale of the remaining shares in the block, so you would inherently have the funds to pay the taxes on the difference. (And if the price fell in that time, you could correspondingly claim a loss to reduce your taxes owed.)
There were a fair number of people who held onto all their shares till it was way down, though, and had to sell a lot to cover their tax bill in early 2022 -- I think if you waited that long you had to sell pretty much all your unlocked shares because the price was well down by tax time (it bottomed out under $30 in early March 2022, then rose for awhile till it was back up over $55 right before tax day, so again, if you were lucky and bet on the timing right, you didn't end up too bad off, but waiting till the day before April 15 was not something I bet a lot of people felt comfortable doing while they were watching the price slide below $50 in late February). I even warned one of the sales reps I worked with, while the price was still up, about the big tax bill he should prepare for, and he was certain I was wrong and that he would only be taxed when he sold, and only on the sale price. (He was of course wrong, but I tried...)
The June unlock was pretty much irrelevant for me because by that point the share price was down under $30 -- it spent the whole month of June after the first week under $35. The highest it went between June 30, 2022 and today, was $44.34. The entire last year it's only made it above $35 on three days, and only closed above $35 on one of them. I figured long-term the company was likely to eventually either become profitable, or get bought, and in either case the price would bump back up.
I was thinking about cutting my losses and cashing out entirely when it dropped below $30 after the June layoffs, and again in November when it was below $20, and then yet again when I left the company in January of this year, but the analyst consensus seemed to be around $32-34 through all of that so I held on -- kinda glad I did now instead of selling at the bottom.
When they show the service awards they don’t even cover 5 years because they don’t have all day.
If it was so bad then you wouldn’t see engineers with 10, 15, or 20 years experience staying there. They already got their money from the IBM purchase so if it were bad then they would leave.
Oh but they don’t innovate anymore.
Summit is coming. Let’s see what gets announced and then a live demo.
Every big, old, stagnant company is full of lifers who won’t move on for any number of reasons. The pay is good enough, at least it’s stable, the devil you know is better than the devil you don’t, yada yada yada. There are people in my life who work in jobs like that. They will openly admit that it sucks, but they are risk averse due to a combination of personality and family circumstances, so they stick it out. Their situation sucks, and they assume everything else sucks too. And often, because they’ve only worked in one place so long, they have a hard time finding other opportunities due to a combination of overly narrow experience and ageism.
The movie Office Space is about exactly the sort of company that is filled with lifers who hate their jobs but stay on the path of least resistance.
(I know absolutely nothing about working at Red Hat, so I’m not trying to make a specific claim about them. But I’ve known people in this situation at IBM and other companies that are too big for their own good.)
I too know several lifers at IBM. One thing I've realized is that staying loyal to a company over several years won't save you from ageism.
Your best defense against ageism may be to save more than 50% of your tech income for about 20 years, then move into management and build empires until the music stops.
> Oh but they don’t innovate anymore.
IBM was #4 in the US last year for patents here: https://www.ificlaims.com/rankings-top-50-2023.htmBefore IBM purchase: travel to clients, build and/or fix their stuff, recommend improvements
After IBM purchase: travel to clients, build and/or fix their stuff, recommend improvements
At least on my side of the aisle I haven't noticed any notable changes in my day to day work for Red Hat. IBM has been very light touch on our consulting services.
HashiCorp had already been sold out since waaaay before this acquisition and I also don’t understand why their engineers are seen as “special”…
They just focus on tried and tested boring SW that big businesses find useful and that's not popular on HN which is more startup and disruption focused.
While Hashicorp hasn’t been exciting for a while, I fail to see how an acquisition from IBM will invigorate excitement, much less even a neutral reaction from many developers.
Hashicorp had a huge hand in defining and popularizing the modern DevOps procedures we now declare as best practices. That’s a torch to hold that would be very difficult for a business like IBM.
Perhaps I missed some things but the core of Ansible feels like it’s continuing it’s path to be much less of a priority over the paid value-adds. I can’t help but to think the core of Hashicorp’s products will go down this path, hence my pessimism.
No, it is not. HN has both a "greybeard" audience that will cheer in "Go boring tech" posts and an "hipster" audience that is heavily start-up and disruption focused as GP was saying. When talking about IBM and acquisitions or similar topics, it's usually the second audience that speaks more.
That doesn't mean that some acquisition really kill the product, but you don't need to be as big and old as IBM to do that.
Fuck IBM.
It's funny to characterise people's beef with IBM as that they're boring, old, and stale when IBM are apparently allergic to anyone over 40.
Also their consultants have been some of the most weaponised incompetence laden, rude, and entitled idiots I've ever had the sincere displeasure to deal with.
IBM are an embarrassment to their own legacy imo.
I was more so commenting on the HN hate for the technology/products aspect. IBM has accomplished FAR more than hashicorp and everyone here acts like they were gods gift to software.
I expect, like RedHat, that the Hashicorp acquisition will result in a lot of startups that do not need enterprise-grade products shifting away from “anything Hashicorp offers that needs to charge money for Hashicorp to stay revenue-positive” and towards “any and all free alternatives that lower the opex of a business”, along with derogatory comments about IBM predictably assigning a non-$0 price for Hashicorp’s future work output.
* IBM had little to do with Red Hat's maneuvers around CentOS (I worked at Red Hat for several years and still have friends there, and nothing anybody there said publicly about CentOS in 2020 or 2023 was materially different from things people there were saying about it internally in 2012). Some people have tried to blame IBM for a general culture shift but as far as I've seen, every bit of the CentOS debacle was laid squarely at the feet of Red Hat staff by most in this industry -- as it should have been, since most of those involved were employed there well before IBM bought the company.
IBM's reputation as an aging dinosaur was well-earned long before it bought Red Hat, and continues to be earned outside it. That earned reputation was why they bought RHT in the first place: IBM Cloud market share was (and still is) declining and they wanted a jumpstart in both revenue and engineering credibility from OpenShift in particular.
I had been wondering who would buy HCP, I sort of figured it was either going to be AWS, Google, or Azure and then I figured the other vendor were going to have support removed (maybe gradually, maybe not.)
Also, IBM has been extremely ageist in their "layoff" policies. They also have declined in quality by outsourcing to low cost/low skill areas.
Self selection, to be sure, but their beefs were mostly about the crushing bureaucracy that was imposed on what was supposed to be a nimble type domain; (network) security is, after all, mostly leapfrog with the black hats.
I will not be taking questions ;-)
- it uses some form of consensus algorithm between all nodes that somehow manages to randomly get the whole cluster into a non working state by simply existing, requiring manual reboots
- Patches randomly introduce new features, often times with breaking changes to current behaviour
- Patches tend to break random different things and even the patches for those patches often don't work
- For some reason the process how to apply updates randomly changes between every couple of patches, making automation all but impossible
- the support doesn't know how $PRODUCT works, which leads to us explaining to them how it actually does things
- It is ridiculously expensive, both in hardware and licensing costs
All of this has been going on for years without any signs of improvement for now, to the point that $COMPANY now avoids IBM if at all possible
But I had a similar experience like yours with PHP, I just couldn't get into it.
That's from someone who did a bunch - Perl, Ruby, Python, Java, C++, Scala.
Syntax is one thing, assembling an application with maintainable code is something else.
Code generation in Golang is something I've found removed a lot of boilerplate.
Also, refactoring my logging statements so I could see the chain of events seemed like work I rarely had to do in other languages.
It's a language the designers of which - with ALL due respect - clearly have not built a modern large application in decades.
I think the reason people find go a bit annoying with the error condition is because go actually treats errors as a primary thought, not an after thought like Python, Java.
My preference is a language like Elixir where most methods have an error-code returning version and a ! version that might raise an exception. Then you (the programmer) can choose what you need. If you're writing a controller method that is for production important code, use explicit. If you're writing tests and just want to catch and handle any exception and log it, use exceptions. Or whatever makes the most sense in each situation.
try {
maybeError := FunctionThrowingValueError()
} catch (ValueError e) {
// do stuff
}
I get at the end of the day it's all semantics, but personally I kinda like the error-specific syntax. If you want to do the normal return path, that's fine, but I prefer the semantics of Rust's Result type (EITHER a result OR an error may be set).To each their own, it's not something I really worry about.
I agree on the logging point but my experience was the explicit error handling and with good test coverage meant we rarely got into situations were we had non-deterministic situation were we relied extensively on logging to resolve. But we also went through several iterations of tuning how we logged errors. It's definitely a rough edge in what is readily available in the language.
This sound a lot of like Apple user arguments about iPhone 1 missing copy & paste over a decade ago.
I am very pedantic about checking responses for errors, but from my experience when working with a team and existing project I see that people notoriously forget to check the result. TBH it is a pain to essentially repeating the boilerplate `if err !=nil ...`.
What's worse is that even documentation skips checks. For example `Close()` method. It's almost always returning error, but I almost never seen anyone check it.
The reason for it, is if you want to use `defer` (which most people do) you would end up with very ugly code.
The other alternative would be to then making sure you place (and properly handle error) close in multiple places (but then you risk of missing a place).
And other solution would be using `goto` in similar way as it is used in Linux Kernel, but there are people who have big problem with it. I had a boss who religiously was against goto (who did not seem to understand Dijkstra's argument), and asked me to remove it even though it made the code more readable.
Standard go error handling maximises for locality. You don't see many "long range" effects where you have to go and read the rest of the code to understand what's going to happen. Ideally everything you need is in the diff in front of you.
Stuff like defer() schedules de-alloc "near" to where things get allocated, you don't have to think about conditionals. If an MR touches only part of a large function you don't have to read the whole thing and understand the control flow.
The relative lack of abstraction limits the "infrastructure" / DSLs that ICs can create which renders code impenetrable to an outside reader. In a lot of C++ codebases you basically can't read an MR without digging into half the program because what looks like a for loop is calling down into a custom iterator, or someone has created a custom allocator or _something_ that means code which looks simple has surprising behaviour.
A partial solution for that problem is to have a LOT of tests, but it manifests in other ways, e.g. figuring out the runtime complexity of a random snippet of C++ can be surprisingly hard without reading a lot of the program.
I personally find these things make go MRs somewhat easier to review than in other languages. IMHO people complaining "it's more annoying to write" (lacking stronger abstractions available in many other languages) are correct but that's not the whole story.
P.S: For Close(), you're right that most examples skip checking the error and maybe it would be better if they didn't. It only costs a few lines to have a function that takes anything Closable and logs an error (usually not much else you can do) but people like to skip that in examples.
type Closable interface {
Close() error
}
func checkedClose(c Closable, resourceName string) {
if err := c.Close(); err != nil {
log.Printf("failed to close %s: %v", resourceName, err)
}
}> Standard go error handling maximises for locality. You don't see many "long range" effects where you have to go and read the rest of the code to understand what's going to happen. Ideally everything you need is in the diff in front of you.
I'm assuming you're comparing to exceptions.
I don't know about that. I think this relies on discipline of the software engineer. I can see for example someone who is strict and only uses exceptions on failures and returns normal responses during usual operation.
With Go you can use errors.Is and errors.As which take away that locality. Or what's worse, you could have someone actually react based on the string of the error message (although with some packages, this might be the only way).
I still see your point though, but I also think Rust implemented what Go was trying to do.
You get a Result type, which you can either match to get the data and check the error, you can also pass it downward (yes, this will take away that locality, but then compiler will warn you if you have a new unhanded error downstream), or you can chose to unwrap without checking error, which will trigger panic on error.
Re: Close() errors yeah most times you would be better off writing the code in place if you really need to handle them. You can make a little helper if you find yourself repeating the same dance a lot. Usually there's not much you can do about close errors though.
Sounds like the problem you have with the error checking relates more to development practice of colleagues than the language.
We used defer frequently. Never considered it ugly.
'goto' (hypothesising here as not used it) and use of exception handling that is expected to be handled at edge of boundary points in codebase can be elegant but does need careful thought and design is my experience. Can hide all sorts of issues, lead to a lot of spurious error handling for those that don't understand the intent. That's the biggest issue I have with implicit (magical) error handling - too many people do it poorly.
That said, in practice I see it following a similar philosophy to java checked exceptions, just with worse semantics.
Personally, I don't like high-boilerplate languages because they train me to start glossing over code, and it's harder for me to keep context when faced with a ton of boilerplate.
I don't hate go. I don't love it either. It's really good at a few things (static binaries, concurrency, backwards and forwards compatibility). I hate the lack of a fully-fleshed out standard library, the package management system is still a bit wonky (although much improved), and a few other aesthetic or minor gripes.
That said there's no language I really love, save maybe kotlin, which has the advantage of the superb java standard library, without all the structural dogma that used to (or still does) plague the language (OOO only, one public class per file, you need to make an anonymous interface to pass around functions, oh wait now we have a streaming API but its super wonky with almost c++ like compilation error messages, hey null pointers are a great idea right oh wait no okay just toss some lombok annotations everywhere).
End of the day though a lot of talented people are golang first and sometimes you just gotta go where the industry does regardless of personal preference. There's a reason scientists are still using FORTRAN after all these years, and why so much heavy math is done in python of all things (yeah yeah I know Cython is a thing and end of the day numpy etc abstract a lot of it out of the way, but a built in csv and json module combined with the super easy syntax made it sticky for data scientists for a reason)
Which kind of proves my point. Even Google struggled to write clean, idiomatic Go.
> I am not used to writing code where 2/3 of it is "if err" statements.
I don't write Go, but I have seen this a lot when reading Go. It seems hard to escape. The same is true for pure C. You really need to check every single function output for errors, else errors compound, and it is much harder to diagnose failures. When I write Java with any kind of I/O, I need careful, tight exception handling so that the exception context will be narrow enough to allow me to diagnose failures after unexpected failures. Error handling is hard to do well in any language.Access forbidden? Log a warning and show a 403 page. Is is JSON? Then return JSON.
Exception-handling in general is a pretty small part of most applications. In Go, MOST of the application is error-handling, often just duplicate code that is a nightmare to maintain. I just don't get why people insist it's somehow better, after we "evolved" from the brute-force way.
But If you are coming from java I can understand the single error handling block is more comfortable, but coming from JavaScript/Typescript it's much more easy to check if err != nil, than to debug errors I forgot to handle, during runtime.
If you are looking at OpenAPI in Golang I can recommend having a look at https://goa.design/. It's a DSL that generates OpenAPI specs and provides an implementation of the endpoints described. Can also generate gRPC from the same definitions.
We found this removed the need to write almost all of the API layer and a lot of the associated validation. We found the generated code including the server element to be production ready from the get go.
For that size of codebase I'd have thought code structure and modularisation would be more important than language choice.
Not a gopher by any stretch, but to my way of thinking code generation is literally boilerplate, that's why its generated. Or does Go have some metaprogramming facilities I'm unaware of?
So unrelated to code generated, if that makes sense. The generated code I'm sure had lots of boilerplate, it's just not code we needed to consider when developing.
I find it very hard to write expressive, easy to read code and more often than not I see people using massive switch-case statements and other, hard to maintain patterns instead of abstracting away things because it's so painful to create abstractions. (The Terraform/OpenTofu codebase is absolutely guilty of this btw, there is a reason why it's over 300k lines of code. There is a lot of procedural code in there with plenty of hidden global scope, so getting anything implemented that touches multiple parts typically requires a lot of contortions.)
It's not a bad language by any stretch, but there are things it is good at and things it is not really suited for.
[1]: [link redacted]
Both slices start out having the same underlying (bigger) array -so appending to one slice can affect the other one.
In the "bonus" part, though, the appends outgrew the original array, so new underlying arrays were allocated (i.e. the slices stopped sharing the same backing array).
Thanks for the heads-up, janosdebugs :)
So, when you slice a slice, if you perform an array operation like “append” while there is existing capacity, it will use that array space for the new value.
When the sliced value is assigned to another variable, it’s not a pointer that’s copied, it’s a new slice value (with the old length). So, this new value thinks it has capacity to overwrite that last array value - and it does.
So, that also overwrites the other slice’s last value.
If you append again, though, you get a (new) expanded array. It’s easier to see with more variables as demonstrated here: https://go.dev/play/p/AZR5E5ALnLR
(Sorry for formatting issues in that link, on phone)
Check out this post for more details: https://go.dev/blog/slices-intro
(In contrast to languages like Haskell and Clojure, which are simple in most of the ways that matter.)
IDK about this, in 2018 I was in a position to pay for their services. They asked for stupid amount of money and got none because they asked so much.
Can't remember what the exact numbers were but but it felt like ElasticSearch or Oracle.
What I thought we really needed was a "starter/enterprise" dual-model pricing structure, so that smaller customers could get pricing in some unit they could understand and budget for, that would naturally and predictably grow as they grew, to a point where it would actually be beneficial to them to switch to client-based pricing -- but there seemed to be a general reluctance to have anything but a single pricing model for any of our products.
Most staff with no equity will leave quickly of course, so the invalidity of non compete will definitely help those souls.
State encryption, provider-defined functions on steroids, removed blocks, and a bunch more things are coming, see our docs for all the details[0].
We've also had a fun live-stream today, covering the improvements we're bringing to provider-defined functions[1].
We're just starting to implement it and we've only heard good things about it.
The problem is it doesn’t go much beyond that, so you’re limited by SSH roundtrip latency and it’s a pain to parallelize (you end up either learning lots of options or mitogen can help). However fundamentally you’re still SSHing to machines, when really at scale you want some kind of agent on the machine (although ansible is a reasonable way to bootstrap something else).
> Requiring minimal configuration changes, it updates Ansible’s slow and wasteful shell-centric implementation with pure-Python equivalents, invoked via highly efficient remote procedure calls to persistent interpreters tunnelled over SSH. No changes are required to target hosts.
Then of course python itself is not very performant and yaml is quite the mess too. With ansible, you have global variables, group level variables that can override them, host level variables that can override those, role level variables, play/book level variables that can override those and ad-hoc level variables that can override all of the above. I am telling you, it can get incredibly messy and needlessly complicated quickly.
As I said though, it's still the best we've got even if not optimal. So I think it's a good idea to implement it to at least have something.
[0]: https://mitogen.networkgenomics.com/ansible_detailed.html
Not used it for about 5 years and I think they got bought by VMWare IIRC. The only downside is that Ansible won the mindshare so you're gonna be more on your own when it comes to writing esoteric formulas.
Interesting that folks are still using it, though I'm not sure of the market share.
And don't get me started on Terraform, which is a promise but rarely delivers. It's bad enough that a whole ecosystem appeared around it (like terragrunt) to patch up the holes in it.