2022 Rivan SDE Summer Intern — Palo Alto

Sam Liao
17 min readAug 21, 2022
660 Hensen Way, Palo Alto

Following the final presentation and my last code commit being merged, my first internship as a software developer comes to the end. As a rookie in computer science, Rivian really gives me a golden opportunity to observe and learn how the industry develops software products. Other than that, I was at the frontline to witness a massive layoff, an application migration on the frontend repo, and the personnel change(my original manager job-hob to Amazon, I like him more than the latter one🙂).

All of these up and down nourish me and give me the chance to not only be a code monkey who merely looks at technical detail, but also zoom out a little bit and see how a mid-size silicon valley company iteratively and incrementally develop its product.

What is Rivian

Rivian’s logo

Rivian is an electric vehicle automaker, which is an adventure-minded company that targets outdoor enthusiasts as their car buyers. According to its official statement, the meaning of the yellow compass logo is inspired by this mechanism of possibility, and for accompanying so many on their journeys north, south, east, west, and everywhere in between.

We have both toB and toC products. In terms of business partners, Amazon is both our significant stakeholder and client(aka sugar daddy👨🏻). They make strategic investments in the auto industry for several years probably to help them cost down their logistics in the future when electric cars are about to dominate the market. Our product for Amazon is called EDV(electric delivery van), they totally ordered 100,000 vans a few years ago and recently we hit the milestone of building the 1,000th EDV! For reference, Rivian built 500 vans between December 2021 and June 2022, and took only another 6 weeks to get to van 1,000!

EDV for Amazon(front)
EDV for Amazon(back)

In terms of toC products, we have R1T which is probably the most heated electric pickup truck in the world, and R1S which is also a high-tech, all-electric SUV. Despite a slow ram-up of EV production, Rivian states that the 2022 output number goal is still on track, with 2,553 EVs being produced and 1227 of them being delivered in Q1 of 2022, according to its report.

Screenshot from Rivian.com

It is not an easy journey for EV startups to cross the obstacle of production capacity. For example, Tesla had difficulty elevating its Model3 sedan production in 2018 that almost force them to go bankrupt; Lucid Motors, which develops all-electric luxury vehicles, has drastically reduced its production target again and again in 2022.

In my opinion, the future for Rivian is still promising once Rivian could keep expanding its production capacity. The market is still potential, the vision and customer target are clear, and the 1st gen product is decent.

Which team I interned at Rivian

Badge

Transaction to Delivery team(T2D) is the org I worked under. T2D provides Rivian customers with the ability to confirm vehicle configuration and complete vehicle purchases in less than 10 minutes online, in their comfortable homes. T2D includes 1. Title/Registration/Fees, 2. Contract(s), 3. Vehicle Purchase and 4. Scheduling Vehicle Delivery. T2D also provides support for Rivian Operational Admins to support customers through their vehicle purchase journey for all T2D features including Last Mile Delivery and scheduling test drives.

Under the T2D engineering team, we could roughly separate the whole team into the transaction(re-marketing, insurance, digital purchase, vehicle registration) and the delivery team(Appointment, Vehicle & Fleet Ops). There are a total of 45 full-time employees including frontend/full-stack engineers, backend engineers, and managers in the T2D Engineer team along with 12 Software Engineer interns including me. In fact, we have more co-workers in the T2D Engineer team before a 35% massive layoff happening in the middle of July, I would elaborate on this shocking news later.

My intern project

Terminology

DMO: Delivery & Mobile Ops Manager.

One of the RivianOS features is to allow customers living at a certain distance from our service centers or factory to come to pick up their vehicle, instead of having it delivered to their homes. The feature facilitates the delivery process for those who want to get their cars as soon as possible. The DMO managers choose this distance (eg: onsite pickup reach is 5 hrs, factory pickup reach is 6 hrs) based on analytics around staff capacity, flatbed capacity, etc. During the end-of-quarter rush, they would like to have the ability to change the “reach” values every week.

Tech stack

Spend time studying those 4 cool stuff the whole summer : )

Frontend: React, Typescript

Backend: Spring micro-services, NetflixDGS, Terraform

Gateway Layer: GraphQL

Database: DynamoDB

Collaboration tool: Confluence, Jira;

Visualization: Figma, LucidChart

Why build this app?

The delivery team has been receiving frequent requests to adjust the on-site pickup and factory pickup configuration value. Currently, these values are hardcoded in our delivery micro-service, which means any request to update these requires a code change and up to 2 hrs to deploy to production. We need the ability to control these values through a user interface.

What does this Delivery Configurator project aim?

Finalized UI display

Delivery configurator MVP aims to address the problem mentioned above by providing a self-serve tool to make these changes on the global level, so adjustments could be made without needing to go through engineering to make a change.

The Delivery Configurator will live within the DMO Manager app and provide the ability to add & update configuration parameters to control delivery functionality. The scope includes the following features:

  • Provide the ability to configure the global radius for on-site pickup and factory pick-up experiences.
  • Restrict the above ability to DMO Managers based on appropriate roles. Provide read-only abilities for basic t2d roles
  • Capture all the actions performed(who, at what time, make what changes), by storing those data into Dynamodb via audit trail service and rendering on the page. For example, Sam changes the onsite config parameters from 2hr to 3 hr on 15:30:30, Aug 22, 2022 .

Design Details

Since access to update configuration values is going to be limited to DMO managers, a new role will be created and used to restrict the access. Both frontend and backend would check current users' authorization to make sure this value won’t be touched by unauthorized users.

Backend

We leverage the existing delivery service to build CRUD APIs and publish the GraphQL endpoints to the Delivery subgraph. Delivery Service can own this configuration data and store it in a new DynamoDB table. The primary reason for storing data is that we want to externalize the config parameters and provide the ability to update them through UI.

The audit trail service will be captured for creating/updating actions involving config parameters. Existing Audit services can be used to capture & display these actions.

Frontend

Styling: Previously we adopt style-component, but in the middle of the internship, the frontend repo start resolving some tech debt by applying several significant migrations, so we pivot to Material UI.

Though there’s a shared component library(SCL) built by the core service team for all Rivian apps to use, it is still not well-integrated and has some deprecated(or not well-designed) stuff. Therefore, in my project, you could find 3 types of components, Pure SCL component, SCL component with custom styling, and self-designed component.

Form Validation: We choose React-hook-form to create performant, flexible, and extensible forms with easy-to-use validation. It reduces the amount of code we need to write for validation while removing unnecessary re-renders.

State management: For comprehensive state management, we discard Redux and use Apollo Client to enable us to manage both local and remote data with GraphQL. Use it to fetch, cache, and modify application data, all while automatically updating the UI. In fact, replacing Redux with Apollo client is what our frontend architecture encourages other engineers to adopt during the migration.

Custome Hook: Learning how to wrap complex component logic into custom hooks is probably a big takeaway during this internship. Custom hooks are sometimes overkilled for small school projects, but after I look into other seniors’ custom hooks which are introduced in multiple apps, I knew how important it is to build reusable, robust, and comprehensive wheels that others could simply import and use without worrying about implementation detail.

Testing: We majorly use the react-test library because its functionality is quite complete and easy to use. For mocking GraphQL query and mutation, we use MockedProvider from @apollo/client/testing.

Takeaway

Rivian really develops their products with the latest cool stuff instead of some legacy tech stack. Since I mostly contributed to the frontend, there’re some points that are worth bringing out:

  1. Code styling varies tremendously

We all know that frontend frameworks and tools move faster and faster in this era. Currently, Typescript has gradually become the industry standard for frontend development given that it solves the pain-point of javascript(such as unclear inputs, expected output, lack of interfaces, enum, lots of undefined problems, etc).

However, there’re still lots of tools and ways to develop in js, and it turns out to be a little bit confused for me when trying to catch up on which way I should code. I still remember that one time I was implementing a functional component consisting of GraphQL requests. I browse through the repo and find that one developer has applied useQuery from Apollo Client that might cover what I want to accomplish, so I write code based on his. However, my mentor commented on my merge request that checked out the GraphQL Code generator since Rivian now uses this to generate code from GraphQL schema. Though the result is the same, I have no choice but to modify my code. Unlike the backend which has typical patterns to follow such as MVC, the frontend is sometimes kind of annoying because of the rapid change and technology migration.

2. Take other's time serious when seeking help from others

When and How to ask people questions is probably one of the most frequent questions that I have asked my mentor. His response is: there’s no right answer, but take others' time seriously because you are blocking others’ productive time. Before asking questions, make sure that you have tried exhaustively to figure out the solution. Usually, it takes at least an hour but still depends. As an intern or new grad in the future, we don’t expect you to know everything. Hence, just keep being curious and asking questions. However, don’t take it personally when people don’t respond to you back immediately. Just be nice and they would be nice back.

By the way, despite my preference of hopping on Zoom call to walk through my problems and thoughts compared to slack messages, not all people like this way probably because they can’t respond at the time they want).

3. Works on 2–3 things at the same time because you wouldn’t be blocked when one of the progress is delayed

It basically means that you are encouraged to switch between branches to play around. It could be some experimental stuff or features that would be built sooner or later. What resonated with me is that once I was waiting for confirmation from a PM for the whole afternoon. I suppose to find other work to do but I just sat there waiting.

Tips: Most of the time, works could be categorized into implementation, code review, and research. Try to do another two when one of them is blocked by either bugs or others’ progress.

4. Negotiate requirement instead of assuming that you have to do it all

There’s always a gap between engineering implementation and product requirements. It is necessary for engineers to know when to push away some unreasonable or trivial requirement for better performance, faster progress, or priority. When I applied react-hook-form to implement custom cross-field validation, PM hopes that the invalid input warning comes before clicking the save button. However, cross-validation would only trigger when onSubmit. After discussing with PM, they accept the tradeoff. If I didn’t make the tradeoff proposal and find other solutions, my time is wasted on the low-priority issue.

5. Always make small changes each time

I mess up with my first MR because I tried to make progress by developing as fast as possible. However, I didn’t check with senior engineers, my implementation is told to be unoptimized and should be replaced with a better one. Thus, always remember: Progress happens when things are not removed or undone. Only jump into implementation after gaining certain confidence and validation on your solution. The concept is quite important even in the technical interview. The lesson learned is that during the process of solving problems, always think out load and confirm with interviewers that I am on the right track before jumping into the implementation.

6. Others tech notes (TLDR, if you are not interested in frontend development, feel free to jump to Timeline header : )

  • Monorepo vs. Multi repo

Our frontend monorepo is seperated into multi(in fact only 2) repo at the middle of the internship. Though I didn’t ask staff engineers the reason behind the decision, I Google the pros and cons and compare the experience developing in mono repo and multi repo. Here is my like and dislike about this migration

❤️ about monorepo

Faster collaboration and communication among Developers

When I want to implement something that probably already done by others, I would use keyword to search relavant code snippet. Within monorepo, lots of template for me to follow. Also, when I was communicating my problem, other engineers could easily see my code and share theirs.

Easier to enforce patterns

With same config setting, it is easier to enforce common patterns and best practices. On the contrary, after the migration, I found out that the repo I am working on and the other repp do things differently.

Simplifying Dependencies Management

Within the monorepo, different application could share functions, component or 3rd party library with each other.

🫤 about monorepo

Performance

As mono-repo keeps growing, it becomes so slow to check out, clone, or pull. Also, file searches is a little bit slower comparing to mutli-repo.

Dependency issue

Since multiple people commit on the same repo, once an app has bug, it would block other app from deploying.

  • useCallback, useMemo

Wrapping function with useCallback or wrapping component with useMemo makes those only render when dependencies change. It is a good way to improve performance to avoid unnecessary re-render. However, not overuse it because comparison also takes time com.

  • Controlled vs Uncontrolled Components

Most of the time, the controlled component is recommended, but using uncontrolled components could reduce the amount of code(such as value、onChange、state ). It is good to be applied when dealing with special cases such as file input, which react hook doesn’t support, or simple cases that we don’t need to get the state value.

  • The advantages of MUI styled component
  1. Writing CSS-in-JS (the style engine would call API to transform code into CSS and embedded into the header of the HTML element)
  2. Support dynamically style change (by passing parameters)
  3. Compressed and optimized
  • Introduce custom hook to extract duplicate component logic

If we observe repetitive work and complicate state management logic, writing a custom hook produces less duplicated code and easier maintenance. A simple case is that when we toggle button to expand and fold the form, we could write useToggle hook to manage the toggle state.

  • Css styling

For container size and font size, em, rem or % is better than px. However, px is widely used in margin, padding, etc.

  • Redux pros and cons

Redux uses this “store”, think of it as a document-like database but for the Frontend. In order to update information, you “dispatch” an action aka run this action that will update the store

pros

  • everything is stored on the FE
  • every component can use it

cons:

  • store maintenance
  • if anything gets out of sync, the FE will be “wrong”

there’s a way to do “redux-like” solution but not as crazy using context api you can do something redux-like but not entirely redux

redux is great for solutions like:

  • permissions and roles
  • ie: my app has a READ_ONLY permission and I want the entire app to hide buttons on every page depending if it’s READ_ONLY

not so great:

  • i want these 2 pages to share the same “store”
  • redux is over engineering the solution
  • in this scenario, if I have 20 page app and I only want 2 pages to use the same store, now all 10 have access.

Timeline

The internship started on 5/30, and ended on 8/19, 2022. The 12-week timeline looks like this:

Week1: Intern-wide onboarding events; Getting up to speed on all things Rivian and T2D; Going through the plan for the summer;

Week2: Diving into the demo starter apps to catch up on the technologies I was gonna use this summer(referencing the tech stack part). Setting up the local environment, which is usually annoying lol.

Week3: Make the first MR(merge request) for the intro project and review others' code. At the same time, drafting design documentation with my backend partner.

Week 4: Start working on the project. Last week my mentor and another backend engineer walked me through the local setup and the high-level structure of the frontend (dc-t2d-fe-internal-tools-web) and backend (dc-service-t2d-delivery) repo.Made the first MR includes the skeleton of the configurator page with dummy data. Had the first informal demo with the team.

the skeleton of the configurator page be like

Week 5: While developing more features, learn to write testing to improve test coverage. Also, discover reusable components in Rivian’s shared component library(SCL)

Week 6, 7: Coding, Debugging, Meeting

Week 8: Resolve some issue that is not relevant to my project because the frontend mono repo is migrated to two separate repo.

Week 9: This week is frustrating for every Rivian employee because the layoff massively affected the T2D team. The overall 5% cut is actually 30% for engineering teams if we exclude manufacturing and operation positions that are guaranteed to be not affected. Lots of people were let go including both principal, senior, and junior levels. It’s a rare opportunity for interns to see all this happen. It also reminds me to always be prepared for the worse while being confident about the future.

It kind of recalls my bad memory of being rejected by Meta after my summer intern offer was rescinded in Feb 2022. But guess what, I get the opportunity to come to California(if I stayed at Meta, my only office option is Washington D.C. ). I met friends with wonderful people, cultivated the habit of cycling, explored mother nature, reunited with old friends, etc.

Week 10: Hooking up frontend and backend with gql. Learned how to write mocking gql query with Mockprovider. In fact, it should be done a week earlier since the next week is the time to wrap up the project and dry run the presentation but I still hadn’t finalized the code until the end of next week. MMy mode switched from 😎 to 👨‍💻.

Week 11: Work on some backend stuff with other micro-service. Finalize my frontend code.

deal with asynchronous issue

Week 12: Presentation & Recharge

Feedback from mentor and manager

There’s a section called recharged in Rivian, it occurs two times, one at week6 and one at week 12. Basically, it is the opportunity for both intern and the manager to provide feedback to each other.

Here is the final feedback from my mentor and manager(I guess most of them are from my mentor since I literally have no idea how much my manager has been involved in my project lol)

1. Please provide details of their accomplishments.

Worked on a wide range of frontend development: React hooks, forms, routing, roles and rights permissions, redux, graphql queries and mutations, unit testing. All while the dc-t2d-fe is being migrated into two separate repos and huge overhaul. Also learned agile methodology and working with team members in software development. I think this cannot be stressed enough since the internal tools is one of the older/bloated repos and he was able to navigate that despite not being familiar with anything to begin with.

2. What’s an area you’ve seen them excel?

Ability to pick up new skills (most of what he has done is something he has not touched before), all while being self-sufficient in cases where I or others are busy. Kept good head on shoulders (faced new challenges without complaints, asked good questions).

3. What is an area you’d like to see them develop post-internship (e.g., knowledge, skills, relationships, experiences)?

Generally, develop more on working with others. For communications that means keeping conversations/meetings relevant and to the point — keep eyes on addressing the original goal of the meeting before going on tangents. In terms of coding, develop more on identifying good design patterns and avoiding bad anti-patterns. Don’t rush things or work on too many things at once — think about a single task first, code that well, test, before moving on to a new one.

Summary

I would rate 7.5 out of 10 for the internship. The 2.5-point improvement room is from the gap between my expectation and reality. Although lots of junior engineers are really supportive and patient, lots of senior+ levels engineers are so busy that the review and feedback comes late. Another point to deduct is that I was contributing to a repo with lots of old codes. Some of them are refactored but some of them aren’t. It confuses me when trying to find a pattern to follow before coding.

Initially, I set to finalize the project within 8 weeks because I feel like the scope of my project is not enough to be outstanding so want to finish earlier and own more tasks. However, I overestimate my ability 😂. Overall speaking, I still learned a lot from the good and bad things that happened in these short 12-week. Rivian’s culture is definitely good, and I would encourage people to work there if getting the opportunity.

Me and my backend partner — Forest
Andres is my best friend at Rivina, we run together every Saturday morning
WFH for 2/3 of the time because of this : )

Reference

--

--

Sam Liao

Taiwanese 🇹🇼| New York | CMU MISM Grad| Runner 🏃 | Coding 💻 | Basketball🏀 | Chess ♟