Series·

Did You Know? 10 Developer Tips from Real Codebases

A collection of practical software development tips, workarounds, and clever solutions discovered in production codebases. Part 1 of an ongoing series.
Did You Know? 10 Developer Tips from Real Codebases

Welcome to "Did You Know?" - a series where we share practical tips, clever workarounds, and non-obvious solutions discovered in real production codebases. These aren't theoretical best practices - they're battle-tested patterns from actual projects.


1. Codemagic Can't Build iOS and macOS Simultaneously (But There's a Workaround)

The Problem: You have a Flutter app targeting both iOS and macOS. You'd expect to build them in one pipeline, but Codemagic doesn't allow selecting both platforms in a single workflow.

Did you know? The solution is to use custom codemagic.yaml files with separate workflows:

workflows:
  ios-build:
    name: iOS Build
    instance_type: mac_mini_m2
    environment:
      xcode: latest
    scripts:
      - flutter build ios --release
    artifacts:
      - build/ios/ipa/*.ipa

  macos-build:
    name: macOS Build
    instance_type: mac_mini_m2
    environment:
      xcode: latest
    scripts:
      - flutter build macos --release
    artifacts:
      - build/macos/**/*.app

You can trigger both workflows in parallel from your CI, or chain them sequentially. The key insight: don't fight the UI limitations - embrace YAML-based configuration for full control.


2. Docker BuildKit Cache Mounts Can Cut Build Times by 80%

The Problem: Every Docker build reinstalls all dependencies from scratch, even if nothing changed.

Did you know? BuildKit cache mounts persist pip and poetry caches across builds:

RUN --mount=type=cache,mode=0755,target=/root/.cache/pip pip install poetry==1.8.4
RUN --mount=type=cache,mode=0755,target=/root/.cache/pypoetry poetry install --no-root

This reuses downloaded packages across builds. A typical Python project with 100+ dependencies goes from 3 minutes to 30 seconds on subsequent builds.


3. One Docker Container, Two Behaviors

The Problem: You need different startup commands for development (hot reload) vs production (gunicorn), but don't want to maintain separate Dockerfiles.

Did you know? You can switch behavior at runtime using environment variables in your command:

command: >
  sh -c "if [ \"$DEVELOPMENT_MODE\" = \"True\" ]; then
    poetry run python manage.py runserver 0.0.0.0:8000;
  else
    gunicorn --bind :8000 --workers 8 streamdatalab.wsgi:application;
  fi"

Same image, different modes. Deploy once, configure per environment.


4. Health Checks Prevent Race Conditions in Docker Compose

The Problem: Your app crashes on startup because the database isn't ready yet, even though you used depends_on.

Did you know? depends_on only waits for the container to start, not for the service to be ready. Use health checks:

depends_on:
  db:
    condition: service_healthy
  redis:
    condition: service_started

# In the db service:
healthcheck:
  test: ["CMD-SHELL", "pg_isready -U myuser"]
  interval: 2s
  timeout: 2s
  retries: 10

Now Docker waits until PostgreSQL actually accepts connections.


5. Celery Workers Can Auto-Restart on Memory Leaks

The Problem: Your Celery workers slowly consume more memory until they get OOM-killed, taking running tasks with them.

Did you know? Celery has a built-in flag to gracefully restart workers that exceed a memory threshold:

command: celery -A myapp worker --loglevel=info --concurrency=4 --max-memory-per-child=100000

Workers restart themselves after processing tasks if they exceed ~100MB. Memory leaks become a minor nuisance instead of a production incident.


6. Firebase's Immutable Cache Headers Give You Free CDN Performance

The Problem: Your static assets (images, fonts, JS bundles) get re-downloaded on every visit, wasting bandwidth and slowing load times.

Did you know? If your assets have hashed filenames (like app.a1b2c3.js), you can cache them forever:

{
  "headers": [
    {
      "source": "**/*.@(jpg|jpeg|gif|png|svg|webp|ico|avif)",
      "headers": [{
        "key": "Cache-Control",
        "value": "public, max-age=31536000, immutable"
      }]
    }
  ]
}

One year cache, marked immutable. Browsers won't even send conditional requests. Combined with Nuxt or Next.js hash-based filenames, cache invalidation happens automatically on deploy.


7. Pre-commit Hooks Can Enforce Conventional Commits

The Problem: Your git history is a mess of "fix", "update", and "wip" messages. You want semantic versioning but can't parse the commits.

Did you know? You can reject non-conventional commits before they're even created:

# .pre-commit-config.yaml
- repo: https://github.com/compilerla/conventional-pre-commit
  rev: v3.0.0
  hooks:
    - id: conventional-pre-commit
      stages: [commit-msg]

Now git commit -m "fixed stuff" fails, but git commit -m "fix: resolve login timeout issue" succeeds. Your changelog writes itself.


8. Shell Scripts Can Fail Fast with Dependency Checks

The Problem: Your startup script fails midway through because a required Python module is missing, leaving the system in a partial state.

Did you know? You can validate critical imports before starting:

#!/usr/bin/env sh
set -eu

# Fail-fast import check
python - <<'PY'
import importlib
for m in ("fastapi", "uvicorn", "sqlalchemy"):
    importlib.import_module(m)
PY

exec python -m uvicorn app.main:app --host 0.0.0.0 --port "$PORT"

If any import fails, the script exits immediately with a clear error. No partial startups.


The Problem: You're using Nuxt's static generation but have to manually list every route for prerendering.

Did you know? Nuxt can automatically discover pages by following internal links:

// nuxt.config.ts
export default defineNuxtConfig({
  nitro: {
    preset: 'static',
    prerender: {
      routes: ['/'],
      crawlLinks: true  // Magic happens here
    }
  }
})

Start from /, and Nuxt will find and prerender every linked page. Add new content, link to it from anywhere, and it's automatically included in the build.


10. AWS in Docker: Disable EC2 Metadata to Force Environment Variables

The Problem: Your containerized app ignores the AWS credentials you set in environment variables and tries to use EC2 metadata (which doesn't exist outside EC2).

Did you know? You can explicitly disable the metadata service:

environment:
  - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
  - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
  - AWS_EC2_METADATA_DISABLED=true
  - AWS_CONTAINER_CREDENTIALS_RELATIVE_URI=

The AWS SDK has a credential chain that checks metadata before environment variables. Disabling metadata forces it to use your explicit credentials.


Bonus: Ruff Lets You Apply Different Rules to Different Paths

Did you know? You can be strict in production code but lenient in tests:

# ruff.toml
[lint.per-file-ignores]
"__init__.py" = ["E402"]  # Allow late imports in init files
"**/tests/*" = ["E402", "S101"]  # Allow assert statements in tests
"**/migrations/*" = ["E501"]  # Allow long lines in migrations

No more disabling rules globally just because they don't apply everywhere.


What's Next?

This is Part 1 of an ongoing series. Each installment will bring 10 new tips from real codebases - no fluff, just practical knowledge.

Got a tip of your own? Found something clever in a codebase you're working on? Let us know - we might feature it in a future edition.


MusicTech Lab specializes in building software for the music industry. We've seen a lot of codebases. Contact us if you're building something interesting.

Need Help with This?

Building something similar or facing technical challenges? We've been there.

Let's talk — no sales pitch, just honest engineering advice.