Great engineering culture reduces time-to-value while protecting users and engineers. It is easier said than done, I find that leading by example is the best way to get your points across. As engineers we hate politics and fluff we want to see meaning in what we do, actions mean more than words.
Unfortunately you can't fake this one. Real trust and motivation will come naturally if you truly care about your team members. Show that you care by doing things for them, help them out when you need them the most, give them autonomy and allow them to make mistakes so they grow. Don't blame and assume positive intent. Share credit and celebrate wins. Share constructive feedback on a regular basis.
When you need to have a difficult conversation share the things you like first then share what you don't like with concrete examples so it easy to understand. If dealing with people doesn't come naturally to you, I highly recommend reading the popular How to Win Friends and Influence People book.
At any point in time there are always many things you can do, that is why it is important to pick your battles wisely. Much better to have a heated argument on how we can we improve 10x the performance of that slow backend route than wasting time discussing if we should use single or double quotes for strings. Although the Pragmatic Programmer book is old, its still my favourite.
Tie work to user value, challenge concepts early to try and achieve 80% of the value for 20% of the effort. Let's say you are building a new notification panel.
What happens if the user has too many unread notifications? Will the number fit in the UI? Will the backend take too much time to calculate the total amount? Will we update the number as notifications are read? Slow down, start again. How about just showing the marker with no number in it? We can easily start with that and iterate later if necessary. Simplicity isn't easy, but it is worth it.
We've all experience the frustration of using a buggy product, it is awful. The user gets the worst part but at the same time the developer gets interrupted to rework the unreliable implementation.
Make sure the work you deliver has monitoring built in. Think if is necessary to create an alert. Write tests that verify the behaviour and give you confidence every time you make a change. If you are in a already in a very unreliable codebase, first take a step back and analyze the root cause of the most common issues and fix them first.
We all make mistakes and it is fine from time to time, but there is nothing more energy draining than having to fix the same issues over and over again.
I've found giving autonomy to talented people is empowering, having one person end to end designing, building, testing, deploying and operating a thin vertical slice of software. It is a good investment to provide tools that allow engineers to comfortably be able to take ownership of each stage of the software development lifecycle.
Product-minded engineers focus their interest in the product they are building, its users, and the business context. Are proactive towards product development, try to understand the "why" behind decisions. They balance product and engineering tradeoffs, handling edge cases pragmatically, and owning the product feature lifecycle.
If your technology stack allows for it, I'm also very fond of full-stack engineers. Every time you can eliminate a handoff you are reducing friction and improving communication.
Especially in remote teams, transparency is key. You need to share all the context early and track decisions to make sure everyone has the best information and a complete picture to do the best work.
Overcommunicate if necessary. Explain the biggest challenges and how we are going to tackle them. Share the vision and the goals. Ask the team to explain the strategy back to you to test how good your communication was.
Split problems into small pieces which can be done in 1-3 days, use feature flags to hide work in progress and showcase feature to beta customers as soon as you have a working solution.
I like to enforce a CI check that disallows merging PRs that are over 500 lines of code changes and make sure every merged PR is deployed to production.
Make sure you have safety nets in place to give the confidence to your team to move fast. The CI/CD pipeline should be solid: static code analysis (linting, type checking, duplicates ...), there should be E2E in place for the most critical paths and have integrations or unit tests for most of the code base.
I'm a big fan of Domain Driven Design (DDD) or Jobs To Be Done (JTBD) frameworks, analyse the problem you are working on and split it up in manageable chunks which have meaning for your end user.
The team structure should mirror the structure of the software. The code base structure should mimic this structure too. The same terms our users use, our product team uses should be in our code base. We have to work to eliminate barriers to communication and avoid unnecessary complexity.
Unfortunately the meaning of DevOps has really been lost over the years in the software community. I really like following the structure shared by the AWS Well-Architected framework. Thankfully the software industry shares its best secrets openly. We can quickly check best practices and benchmark metrics to understand where you are and what is missing to become an elite team.
As the number of employees grows and the time working on the project increases, the most value you are going to get from every operation improvement. As you grow in number of users the more value you will get from investments in reliability, performance and security.
Start measuring what matters to understand your main bottlenecks, then work to improve and track your progress.
Kind but direct communication, iteration over grand plans, user empathy, high standards, pragmatic execution, and don't forget to fight complexity or it will end up stalling your progress.