Skip to content
Chris Chen

Professional Journal

The Art of Journaling by Ryan Holiday (also one of my favourite authors)

I use Notion to jot down interesting things I picked up at work. Periodically, I revisit and clean up journal items, then migrate them to here.


RACV (2020-2021)

Lesson learned

  • Finally met a good tech lead who
    • has no big ego, does not try to be the loudest voice
    • thinks through tasks beforehand, assesses technical solutions and challenges
    • kicks off tasks with individual engineers, hashes out ideas and concerns
    • writes code review comments with proposed code snippet
    • is willing to work on the not so glorious tech debts in the background
    • walks through his code changes with fellow engineers
    • again, a humble tech lead, not a jerk
  • Technical decisions that caused high codebase maintenance overhead and steep learning curve for newcomers:
    • Dependency Injection in Javascript codebase, without a typing system
    • Hand-crafted GraphQL resolvers, without a convenient framework
  • How to write a comprehensive system architecture design document
  • How to plan a reasonable workload for each sprint and achieve complete burn-down

Tech skills learned

  • Infra / DevOps

  • Node.js backend

    • use AWS SSM and Secrets Manager for deployment configuration and env vars ⭐️
    • modularise and isolate data model CRUD operation around the domain
    • npm ci
      1# yarn equivalent
      2yarn install --frozen-lockfile
    • eslint-no-return-await
    • sanitize-html ⭐️
    • lodash.template - lightweight than handlebars ⭐️
    • - see npm dependencies graph
    • optional chaining - available in node.js
    • umzug - framework-agnostic SQL-like DB migration tool for Node ⭐️
    • use key-value pairs to replace large switch-case-return ⭐️
    • knex.js - lightweight than TypeORM, suitable for Lambda function
  • SQL

  • React/React Native frontend

    1const TimeContext = createContext({
    2 now: new Date(),
    3 updateTimeContext: () => {},
    6const TimeProvider = ({ children }) => {
    7 const FORTY_SECONDS = 40000;
    8 const [now, setNow] = useState(new Date());
    10 const updateTimeContext = () => setNow(new Date());
    11 useInterval(updateTimeContext, FORTY_SECONDS);
    13 return (
    14 <TimeContext.Provider value={{ now, updateTimeContext }}>
    15 {children}
    16 </TimeContext.Provider>
    17 );
    20export default TimeProvider;
    21export { TimeContext };
  • GraphQL

  • serverless

    • Authenticate API Gateway with Cognito User Pool, using Amplify libs on frontend
    • serverless-jetpack - speed up serverless framework deployment
    • fine-tune deployment package, example:
    2 exclude:
    3 - '*'
    4 - '*/**'
    5 - '!node_modules/**'
    6 include:
    7 - package.json
    8 - 'src/**'
    9 - '!src/**/__tests__'
    10 - '!src/**/__mocks__'
    • locally invoke Lambda function to perform tasks like RDS migrations, ad-hoc data reporting ⭐️
    • npm chrome-aws-lambda - so we could render React component as PDF ⭐️

Mr Yum (2019-2020)

Lesson learned: Monolith Hell + Kubernetes = Monolith Hell

  • Single Point of Failure vs. Monolith Reliability: an ElasticCache (Redis) node was deeply coupled with the monolith Node.js servers. Due to a bad code commit (millisecond vs second), the ElasticCache node ran out of memory soon after deployment. The Kubernetes nodes started to crash one after another. The whole production system was brought down to its knee.

ElasticCache ran out of memory on 1st Mar 2020 ElasticCache ran out of memory on 1st Mar 2020

  • Engineering cannot keep up with business growth: more food ordering logic, more POS integrations, more payment processors, all in one Node.js code repo, oh my! Before leaving the startup, I tried really hard to dump my brain into the following diagram, and I felt anything but proud.

Even modularised, things were still bundled in one code repo and deployment. Even modularised, things were still bundled in one code repo and deployment.

Tech skills learned

Liven (2019)

Lessons learned

  • Tech co-founder was bogged down with perpetual tech work, didn't have time/opportunity/willingness to grow leadership skills and business acumen.
  • DON’T overdo your JIRA boards/projects setup, especially in a startup.
  • Back-end server needs an adapter pattern for the payment processor. Early-integrated Stripe is very likely to be poached by other intenders.

Tech skills learned

  • Services
    • Leanplum
    • Segment
    • Typeform feedback -> slack
  • iOS
    • Too many client API requests can choke the app performance
    • Use protocol to regulate class public interface, and property ready/write permission
    • Use broadcast/observer pattern to replace sending notification
    • Coordinator pattern
    • Use enum to define API endpoints (Moya)
    • dequeueReusableCellWithIdentifier:NSStringFromClass([AccountTableViewCell class])
    • Upload dsym ASAP so can pick it up
    • Use in-class enum to contain all the styles, similar to RN styles
    • Apple Pay device check
    • NumberFormatter
    • Simulate deep link with this command line
    1xcrun simctl openurl booted
  • Android
  • Python/Django