My Life as a CTO - Technology (Day 1)
Since the title 'CTO' includes the word 'Technology,' it's essential that this series of articles starts with Technology! I divide this part into two main categories: the first category is what you should pay attention to on your 'First Day' if you're starting from scratch, and the second category is 'Daily Life,' what a Tech leader should do every day and where most of their focus should be.
Again, this isn't the standard answer, just a sharing of my personal experience, and any questions or discussions are welcome!
All things are difficult before they are easy.
Day 1, how important yet unimportant this day can be. You hurriedly decide on your tech stack, full of things you want to accomplish, features you want to perfect, and products you want to test quickly. So, it's best to get these preliminary tasks out of the way because plenty of market feedback is critical to determining the fate of your idea. BUT! These foundational tasks might stay with your product forever. The world of software and startups is like a fast-flowing river, always pushing you forward, never allowing you to stop and tidy up the path you've laid. A rushed decision made today might cause you immense pain for the whole next unique. So, even though startups are still under time pressure and launching products for testing is still a priority, you can't be careless when laying the groundwork. Here are three decisions I think you must make, and some criteria you can refer to when making them:
✍️ First Day: Language & Framework
If you're one of the first or very early members, your first decision should be which framework and language to use. However, as the saying goes in the software world, 'there is no best answer, only less crappy choices.' Each option has its pros and cons. If you are working on very specific deep tech, there may only be one or two choices, but if you're developing something more general like a web app, here are some bases for consideration:
Your familiarity: In the startup world, time is everything. Therefore, the ability to develop quickly is a critical factor. Instead of choosing the latest trendy framework that you'd need to learn from scratch, opt for the most familiar one that can handle rapid iterations in the early product development phase and ensure safety from weird bugs. Another benefit is that if you are a veteran in a particular language, you can use 'teaching' as an incentive to persuade new engineers to join your team. After all, learning from a guru is often a key factor in deciding whether to join a company.
Recruitment difficulty: Even if you can initially do the work of ten people, as you grow, your startup team will need to expand. One of the first questions new engineers will ask is what stack you use. While the language you use may not be an absolute dealbreaker, a good choice can definitely be a plus. For example, Cooby initially chose Python because it was the language the team was most familiar with. However, after some time, we decided to transition some services to Golang, not only because of Golang’s effectiveness with multi-threading and speed of language processing but also because at the time (2021), Web3 was booming, and almost all Web3 teams were using Golang. If we were to compete for talent with them, using Golang at least put us on the same starting line. During interviews, I indeed heard many candidates brighten up when they learned we used Golang, clearly seeing it as a plus. In contrast, some older companies still using PHP (I won't say which ones 😇) might deter potential hires unless they offer other attractive conditions. However, a downside of using newer languages is that there are fewer veterans familiar with them, often requiring the team to research best practices together. If you do find a veteran, the compensation package needed will also be much higher, a clear trade-off.
Personal preference: One of the perks of being an early member is that you can make choices based on personal preference (the first person always has the most power!). I personally prefer languages with lower degrees of freedom, i.e., those that are heavily standardized, ideally typed, where everyone’s code looks more or less the same. Although less freedom can be boring, it has many benefits in terms of code review, ease of getting up to speed, and debugging. For instance, Cooby's backend currently uses both Python and Golang, but the Golang codebase is clearly much easier to read and more orderly than Python, even though we also use a typed framework for Python (of course, it doesn't rule out that Golang was refactored later 😅). Using the Gin framework also ensures that there are clear norms about where to do what, making it extremely straightforward to write. Additionally, a recent discovery is that Co-Pilot's auto-complete is more accurate, almost always delivering content that's 90% perfect right after hitting tab.
Language-specific features: There are plenty of professional articles online comparing these features, so I won't go into detail here. I'll attach a link to Perplexity's response for your reference.
✍ First Day: Coding Style & Naming
“Culture is not like a mission statement; you can’t just set it up and have it last forever. There’s a saying in the military that if you see something below standard and do nothing, then you’ve set a new standard. This is also true of culture — if you see something off-culture and ignore it, you’ve created a new culture.”
— Ben Horowitz, What You Do Is Who You Are: How to Create Your Business Culture
The above description of culture perfectly applies to coding style. Coding style and naming are traps that can easily be glossed over early on with a mindset of, "Ah! As long as it works, it’s fine," pushed by time pressure and scarce resources. Styling is always the first thing to be deprioritized, with the mindset of getting things done first and refactoring later. But trust me, once those ugly codes are committed, they will never be touched again; they will lie rotting in your codebase, cursed by everyone and yet saved by no one. So, establishing your codebase's style and naming principles early is crucial. At the very least, ensure consistency. Often, others are not unwilling to follow, but simply don’t know what to follow (there are three styles in the codebase; which one should I write?). So, defining these norms early can make subsequent work much more efficient. Additionally, take 'coding style and naming' very seriously during PR reviews. Sometimes, the focus of PR reviews is only on whether the feature works, but whether it works is something the author should check thoroughly themselves. The PR reviewer’s job is to catch the mistakes the author can’t see, including edge cases, and coding style and naming are often the author’s blind spots. Be brave in catching errors and requesting changes to prevent the 'broken windows theory' and avoid the entire codebase decaying together.
If you're too lazy to define a bunch of stuff yourself, I recommend starting with a popular style from the internet as a base and adding your customized parts. For Golang, I highly recommend Uber's style guide, which is very comprehensive and provides reasons for the norms.
✍ First Day: Cloud Choice
Unless your company is dealing with topics that need very local system support, such as banking, you'll almost certainly face the choice of which cloud to use. The current options include AWS, GCP, and Azure. This choice is similar to selecting a Language & Framework, but in addition to the previously mentioned factors, there are other aspects to consider:
Customer support: Since these platforms are not free like languages, good customer support is crucial, especially when you have new projects or architectures to work on. Having professional internal architects discuss with you can often make the work much more effective. For instance, Cooby uses AWS services mainly because I'm more familiar with AWS compared to other platforms. AWS architects in Taiwan and the USA have discussed with us, helping us make several key decisions during our 2022 backend infra redesign and boosting our confidence in our design. I believe GCP and Azure also offer this kind of support, but I'm not as familiar with them, so make sure to do your research before diving in.
Cost: Financially, the three major providers are similar, with none currently using "cost efficiency" as their main selling point. However, startups often get many discounts, as these cloud providers know that switching the entire cloud infra is a hassle and almost never happens. The initial choice of a startup basically determines which company will bill them for the next few years (usually the largest bill), so they are generous with early credits for startups, fattening you up before the slaughter, so to speak. For example, AWS initially gave us USD 25K of credit to use within two years, which seemed excessive for us at the start—impossible to use up in two years. Yet, we ended up using all 25K in a year and a half and started paying, proving that the most expensive things can be free, but remember to take the credits you're offered!
Community: According to rumors, AWS's community is still the largest among the three, so when problems arise, it's easier to find a giant's shoulders to stand on. However, nowadays, I often ask ChatGPT for everything, especially since ChatGPT has read through all AWS operations, with a very high resolution rate. I rarely rely on the Community anymore (sorry, StackOverflow). I believe the other two providers are no big deal for ChatGPT either, so I think this factor is of lower importance.
💫 Bonus: Github Account Selection
Whether the company's GitHub allows engineers to use their own accounts might seem like a small issue but was discovered to be quite significant after discussions with the team. At first, I didn't think much of it and let engineers join with their own emails. Later, I thought this might pose a security issue, so we switched to creating accounts dedicated to Cooby. However, it wasn't long before engineers suggested they wanted to use their own accounts, prompting me to study the issue more closely.
Here are some pros and cons:
Every engineer using a company-provided new account
The most direct benefit, of course, is ease of management and less concern about security since the account can be terminated if an engineer leaves. However, the downside is that account switching can sometimes be a hassle, and if engineers care about their green dots (contribution graph), they won't be able to accumulate the code they write at the company, unable to pursue the achievement of committing code every day (a lot of people care about this!).
Every engineer using their own account
The advantages and disadvantages are the opposite of the above. It's convenient, familiar, many settings don't need to be reset, company commits can count towards the green dots, and no account switching is needed. As for the disadvantages, many mention security, but I think it's manageable as long as all repos are owned at the organization level, and any account can be easily removed. Therefore, when the company is still small, I generally recommend letting everyone use their own accounts to join.
Having covered the important foundations for Day 1, let's move on to the daily routine.