17 Tips to Convert Your Internship to a Full-time Offer!
October 24, 2020
11 min read
Check this post out on YouTube!
Consider subscribing while you're there?
Throughout my university degree, I’ve completed 3 internships: one at a cybersecurity startup, and two internships at Facebook. I believe that the feedback I’d received from my previous internships really helped in securing a return offer.
This advice is generic to all software engineering internships but to give you an example of the difference this advice makes, let’s compare my two internships at Facebook:
In my first internship at Facebook, I worked pretty steadily towards my internship project, and completed the project by the final review, and rolled it out for employee dogfooding. I didn’t have time to ship it to production by the end of the internship, so it lay in dogfooding for a year:
During my second internship at Facebook, I completed my assigned internship project in 4 and a half weeks, and completed two other projects during the internship, the last of which I was given full rein to scope out myself.
I was literally 3x more productive than during my first internship at Facebook!
The eagle-eyed amongst you will notice I shipped my second internship’s project before my first one!
The single biggest factor to all of this is that I didn’t get stuck on a task for a long time. Usually the biggest drain of our time is just being stuck and not knowing what to do; the actual act of programming is comparatively short.
So how do you unblock yourself?
This is the #1 hack to being productive in your internship and something I didn’t do nearly enough first time round at FB.
It might seem counter-intuitive - surely asking a lot of questions means you’re a burden to your manager and wasting other people’s time? And that you’re not independent enough? Well, so long as you spend a bit of time searching internal wikis / internet beforehand and clearly explain what specifically you’re struggling with, the other full-timers will be glad to help!
My first intern manager explained it to me by discussing team hours - if I spend 2 hours stuck on something, that’s 2 team hours spent on that task, compared to only 10 team minutes if I ask someone else.
Definitely bias towards asking questions when ramping up - the more questions you ask, the quicker you’ll ramp up and the quicker you’ll start shipping code and making an impact. And that impact far outweighs the questions you asked at the start of the internship - your productivity is like an exponential curve!
This might seem obvious, but it’s still worth reiterating. Social media often promotes an unhealthy “superhuman” culture, which idolises people who work 100 hour+ weeks. Setting boundaries when working remotely is really important - I personally used the 10am daily stand-up meeting and my dinner to define my work boundaries (10am to 6:30pm).
Most tech companies care more about results than time put in, and actually some managers will advise against promotions / return offers if they think the amount you’re working is unsustainable (especially important if you’re super keen!).
It’s all too easy to get paralysed by a lack of knowledge, especially if you’re in a completely new tech stack. The mantra I have to get myself moving is to learn on a need-to-know basis: just enough to finish my task, not necessarily to understand all the details.
One way I learn “just enough” is to learn by example from existing code in the codebase. Not sure how
someComplicatedFunction is meant to be used? Search for all the
someComplicatedFunction function call sites in the codebase and go through each call site in turn.
I like to think of this as an iterative deepening approach to learning - you can always go back and learn it more in depth, but breaking off as small a chunk as possible helps you get going and…
Often what you’re evaluated on as an intern is your assigned project. So whilst learning and exploring beyond your team is something I wholeheartedly endorse, it should not come at the expense of your project.
Do a good job on your main project first, then you’ll be free to try new things without the pressure of the project deadlines!
The tighter your feedback loop, the quicker you’ll be able to correct course. Remember, getting feedback early saves team hours! It also improves the odds of you getting a return offer - if you have a performance review 5 weeks in, but you ask your manager for feedback 2 weeks in, that gives you 3 weeks until the review to work on the areas that need improvement!
Ways you can do this:
- Split code into small commits - these are much easier to review, and you can get feedback for one commit whilst you are working on later commits.
- Submit work-in-progress versions of your code if you’re stuck - having code to look at makes it much easier for your teammates to help you out.
- Write design docs / plans of action. Writing down a plan helps clarify parts of the task you’re unsure of, and for others to clear things up.
You see that internship project plan with clearly laid out milestones? It’s a lot more flexible than you think.
Plan out your project in terms of dependencies and work on a later milestone if you’re blocked on the current milestone.
E.g. if you’re waiting on the designs for your frontend UI milestone, start work on the backend milestone.
Better yet, ping the designer early and proactively arrange meetings to provide them technical feedback. If you can unblock them, then it will speed up your project.
There’s no point churning out code if it requires significant code review, or worse, needs to be rewritten during / after your internship. Remember the whole team hours we mentioned - if it takes you an hour to write some code, but then 3 hours of back-and-forth review and revisions, that’s much worse than spending 2 hours writing the same code, but getting it signed off after 15 minutes of review.
As an intern, you’re not expected to be able to churn out line-perfect code from day one - the most important thing is to show improvement.
As we said earlier, the quickest way to ramp-up is to get feedback. It’s much better to push out code even if you’re not sure it’s the best way of doing things, than to spend time stuck. So feel free to make mistakes - you’re an intern so you’re not going to be judged too harshly! Just note down the kinds of things flagged at code review and keep a checklist to go over the next time you submit for review.
The general trend the managers are looking for is that you don’t repeat the same kinds of mistakes (you respond to feedback) and that the amount of feedback / revision needed decreases over time.
Hacking around seems good for exploratory solutions, but you’re incurring technical debt, which is especially costly for large features. See, whilst you speed up the first 80% of development (as you get something working quick), the last 20% of polishing and paying back the debt is what really slows you down. I encountered this a lot in my first internship where I’d think I was blasting through a task until I hit the polishing wall…
More crucially, hacking and copy-pasting code also makes you a little myopic, as all you’re focused about is getting the code to work, when instead you should…
Codebases evolve. The code you check-in now will be used by someone else (and likely yourself!) so it is worth thinking about the manageability of the code - how much code will need to be changed for someone to extend your code to cover another use case? (This is dubbed the blast radius of the code).
Think about why you’re doing the task, not just what the task is. This will help you figure out how your code might be used in the future.
Just because it got accepted for code review in the past, doesn’t mean it’s good code! Best practices change over time, as people discover better design patterns (think React hooks!). It’s also easy to forget that the person who wrote the code is also human, and might have cut corners to meet a deadline. Equally, reviewers may not catch all bugs!
This leads nicely onto the next point:
It’s easy to get trapped in a mindset of just ticking off tasks set in your internship, but remember you’re still a valuable member of the team, so don’t be afraid to contribute further:
Contribute to the wiki - you’ve got a fresh perspective having just ramped up, so you’ll know which bits of the codebase you found especially hard to understand. Fix bugs, write tests that catch them. File tasks about parts of the codebase you think can be improved. Refactor the codebase so it is in a better state after you left it.
All these things demonstrate initiative and will really distinguish you from other interns.
Reading other team members’ code gives you a broader picture of what your team is working on and is also a good way of learning best practices.
Reviewing code feels daunting and the power dynamics seem wrong - how can I as an intern know how to write better code than a full-timer? The full-timers are human too, and a fresh pair of eyes on the code can pick up errors they might not have spotted. This way you’re also contributing to improving the code quality through your feedback.
Not sure how to start? Look at how other team members review code. One trick I used was to review a coworker’s commit, and afterwards look at what else my manager spotted when reviewing that commit. Like with code reviews on my own code, I kept a checklist of the kinds of things he was spotting, so I could provide better feedback.
Reviewing code has a secondary benefit - you write better code. The more you review code, the more you spot the code “smells” (bad practices) in your own code, and therefore speed up code review for everyone involved. Before you submit your code for review, submit it as a “draft” in the review tool and go over it in the review tool.
Ah you thought I’d forgotten about them!
Tests are not just about your code working now, but are for people who change your code in the future - they prevent regressions.
Writing tests actually differs in practice to what you might be taught in school. The ideal scenario is to test every edge case, but in reality your shipping deadlines may just be too soon. It might also be way too much effort to mock all objects and set up all the boilerplate test code. The real world is messy!
For example, I found the Java codebase last summer was more amenable to unit tests and integration tests, whilst other UI changes often only required screenshots. Some changes required an end-to-end walkthrough the entire application flow.
Some testing frameworks really reduce the friction of testing:
Since testing can depend on the team and the tech used, the best way to find out how to test your code is often to just ask your team!
You’ve written your code, tested it, and it’s been signed off after code review. All done? Not quite - we need to check that it is actually working correctly in production.
Add logging so you can monitor which paths of execution are taken. Have kill-switches in the configeration file of your production code, so you can “switch off” a feature in production quickly, rather than having to wait for a fix to be pushed out. Think about rate-limiting if you have particularly high load and don’t want to overwhelm your databases. Think about how you might A/B test a new feature.
During my first internship at Facebook, I rolled out a feature that caused a massive spike in logging. My first thoughts were that I hadn’t correctly rate-limited the code and that there might be a bug in the counter. As I tried to quickly submit a fix, my manager sat next to me and said we should go through the code first. Taking a step back, we realised that the features’s rate-limiting was working, but that I had inserted the logging statement outside the scope of the rate-limiter.
A good way of finding the root causes is the “5 Whys” technique. Why did failure/issue X happen? Because of Y. Okay, well why did Y happen - shouldn’t we have counter measures in place? Because of Z. etc. Big production bugs are usually cumulative logic bugs that interact rather than one issue.
During my first internship’s midpoint review, my manager flagged that I needed to work on my communication. I thought I’d been communicating fine - I’d given updates during meetings and messaged my manager with regular updates. And I wasn’t alone - this was a common trend I saw with other interns too.
In my second internship, the midpoint review was the opposite - communication was my strongest axis of performance. The key? Over-communication.
At many tech companies, engineers drive the product roadmap. As an intern, you drive your project roadmap, and communicating often means that other people can work to unblock you.
Regularly post updates about your project to the wider team. These can be when you’ve achieved key milestones, start-of-week updates, or if you’re scoping out a new feature and want feedback.
Regular update posts make writing your self-reviews much easier, as you’ve already been reviewing your internship at regular intervals through these posts! They also make your manager and other team members’ reviews easier to write, as they don’t need to crawl through your day-to-day work, so they’ll be more likely to give you a good review!
Arrange meetings to discuss next steps in your project. For example, if you’re scoping out a new data model, it might be worth chatting with the team that designed the original data model to understand their design decisions.
By data tooling I mean SQL, querying the logs, or whatever data dashboards the company uses.
Yes, you might be a software engineer, not a data scientist. However, it is still useful to be able to substantiate your points with production data. Why was the rollout a success? Because these logs show a decrease in errors over the last 5 days. Why prioritise feature X over feature Y? Feature X has 1.4x the number of users using it.
Your internship isn’t just about work, but also about meeting new people. Many of the moments that enriched the internship for me (and convinced me to return full-time) were when I met people in other parts of the office at social events.
This naturally was much easier before the pandemic. It’s much more daunting to reach out over messages and set up a video call, but I’ve been pleasantly surprised by how willing people are to having a chat. I assumed my team manager was likely too busy to speak with an intern, so I only scheduled a follow-up call with him late in the internship. He ended up suggesting we extend our meeting from 30 mins to 45 mins and gave some excellent advice about whether or not to do a PhD. I spent most of my last couple of weeks reaching out to people I’d spoken with the previous summer, and in hindsight I only wished I’d done this earlier in the internship!
Whilst I’ve framed this as tips to “ace” your internship, really the key takeaway is that an internship is an opportunity to learn. If you aim to grow and learn, you’ll likely become good enough to secure a return offer as a byproduct, and if you don’t, you’ll be in a much better position next time around.
In a nutshell: observe best practices from your team members, bias towards over-communicating with them and actively seek out feedback and opportunities to push further. And ask questions!
Have I missed something? Let me know on Twitter!