惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 三生石上(FineUI控件)
GbyAI
GbyAI
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
I
InfoQ
Latest news
Latest news
H
Help Net Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
The Exploit Database - CXSecurity.com
雷峰网
雷峰网
Know Your Adversary
Know Your Adversary
人人都是产品经理
人人都是产品经理
C
Cisco Blogs
NISL@THU
NISL@THU
P
Proofpoint News Feed
Y
Y Combinator Blog
I
Intezer
博客园_首页
P
Proofpoint News Feed
Spread Privacy
Spread Privacy
C
CERT Recently Published Vulnerability Notes
G
Google Developers Blog
P
Privacy & Cybersecurity Law Blog
MyScale Blog
MyScale Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
有赞技术团队
有赞技术团队
S
Schneier on Security
N
Netflix TechBlog - Medium
C
Cybersecurity and Infrastructure Security Agency CISA
T
The Blog of Author Tim Ferriss
K
Kaspersky official blog
博客园 - 聂微东
S
Securelist
Recent Announcements
Recent Announcements
A
About on SuperTechFans
Microsoft Azure Blog
Microsoft Azure Blog
Last Week in AI
Last Week in AI
大猫的无限游戏
大猫的无限游戏
宝玉的分享
宝玉的分享
The GitHub Blog
The GitHub Blog
博客园 - 司徒正美
Vercel News
Vercel News
WordPress大学
WordPress大学
M
MIT News - Artificial intelligence
U
Unit 42
T
Tailwind CSS Blog
云风的 BLOG
云风的 BLOG
B
Blog
aimingoo的专栏
aimingoo的专栏
H
Hackread – Cybersecurity News, Data Breaches, AI and More

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
I shipped an iOS app with zero third-party dependencies
Simple Memo · 2026-05-12 · via DEV Community

At 11:47 PM on a Sunday, I deleted the last import Alamofire from my Xcode project. I replaced eight network calls with seventeen lines of URLSession code. The unit tests passed. The app cold-started about 80 milliseconds faster. I went to bed.

That was the moment I committed to a rule I have not broken since: the iOS app I'm shipping carries zero third-party dependencies. Twelve months later, it is the single most contentious thing about how I work as a solo dev.

TL;DR

  • Twelve months of zero third-party dependencies on a small iOS app got my IPA to about 2.1 MB and my cold start to 280 ms median, in exchange for roughly two weekends of work I would have skipped with off-the-shelf libraries.
  • The biggest win is not performance. It is that every line of Swift in the project is debuggable by me, with no source-map archaeology and no vendored module to apologize for at 1 AM.
  • The rule is not absolute. I would add a third-party library tomorrow if it solved a problem I could not reasonably solve myself in one weekend, with tests, and with a maintainer who actually answers issues.

The setup

I am a solo developer. I ship an iOS app called Captio-style Simple Memo. It does one thing: you type a note, you tap a button, the note is in your email inbox in roughly 0.3 seconds. No accounts. No sync. No cloud database. The whole product is a thin UI on top of MFMailComposeViewController, a small encryption layer for the local draft cache, and a handful of system frameworks.

The first prototype, in late 2024, used three third-party Swift packages: SnapKit for layout, KeychainAccess for secure storage, and a small async HTTP wrapper around URLSession I had cargo-culted from my last job. None of them were strictly necessary. All three were habits.

By month two, two things had happened. The IPA had drifted past 6 MB. Cold-start times measured on my old iPhone 12 mini moved from 220 ms to 410 ms. Neither number is ruinous on paper. But for an app whose entire identity is "you tap, the email goes," half a second of warmup is the product. So I started cutting.

What I tried first (and why it failed)

The obvious play was triage. Keep the libraries that earned their weight, drop the rest. I made a spreadsheet. Each row: a third-party dependency. Each column: bytes added, build-time added, time-to-replace estimated in hours, unique value over Apple's SDK.

It looked rational. It also failed. The triage spreadsheet got me to drop SnapKit, which I should have dropped on day one. It got me to keep KeychainAccess, because the time-to-replace estimate was four hours and I told myself four hours was too much. Three months later I needed to support an experimental share target that KeychainAccess did not handle cleanly in my setup. I burned six hours wrestling with the library before I gave up and wrote 60 lines of SecItemAdd / SecItemCopyMatching directly. The wrapper had saved me four hours up front and cost me six on the day I needed it most.

That was the moment the rule stopped being aesthetic. I was not removing dependencies because zero-dependency code is morally superior. I was removing them because every dependency I keep is a future morning I do not control.

The thing that actually worked

I rewrote the rule. Instead of "fewest dependencies possible," I wrote this in my project README:

A third-party dependency is allowed only if it would take me longer than one weekend to write a correct, well-tested replacement, AND the dependency is actively maintained, AND it has fewer than three transitive dependencies of its own, AND it ships with tests I can read.

The change is subtle but important. The old rule was a bias. The new rule is a gate. It forces me to do a tiny piece of estimation up front. It also forces me to confront an uncomfortable fact: most of the third-party libraries I had reached for in the past were not in the "longer than one weekend" bucket. They were in the "I never bothered to learn the system API" bucket.

Here is what fell out the other side of that gate, in twelve months of shipping:

  • Networking: 38 lines of URLSession plus a tiny Result-based wrapper. Replaced Alamofire and one custom in-house wrapper.
  • Keychain access: 62 lines wrapping SecItem*. Replaced KeychainAccess.
  • Layout: native Auto Layout with a small set of NSLayoutConstraint helper extensions, about 40 lines. Replaced SnapKit.
  • JSON: Codable. There was never a real reason to keep SwiftyJSON.
  • Logging: OSLog. There was never a reason to keep CocoaLumberjack.
  • Crash reporting: I do not have third-party crash reporting. I have MetricKit, a handful of TestFlight users who actually report issues, and a hard rule that any crash on launch is a release blocker.
  • Encryption for the local draft cache: AES-GCM via CryptoKit, plus about 90 lines of file-format glue I wrote myself. Replaced a small encryption helper library.

Total third-party packages in the shipping app today: zero. Total lines of code I wrote that exist solely to replace those libraries: roughly 300. Total time spent writing those 300 lines, including tests and rewrites: about 18 hours across twelve months. Two weekends, conservatively.

The numbers I care about, measured on a fresh install on an iPhone 12 mini:

  • IPA size: 2.1 MB
  • Cold start (icon tap to first usable frame): 280 ms median over 50 launches
  • Time-to-email-sent from first tap: median 312 ms
  • Build time, clean: 11 seconds
  • SwiftPM resolve time: 0 seconds, because there is nothing to resolve

I am not pretending these numbers are amazing. For an app that does one thing, they are roughly the floor. The point is that the floor was reachable, by one person, in evenings, without a heroic engineering budget, and without any meaningful sacrifice in code quality on the parts I actually care about. Most of that was simply the absence of work I would have otherwise been doing: no integration glue, no version-pin debates with myself, and no "this library moved to v3, here are the breaking changes" weekends I had not budgeted for.

Why does this matter for a small app?

There is a quieter reason I kept the rule. Every Swift Package Manager dependency I add is a small bet on someone else's calendar. If the maintainer of a 3,000-star library posts a deprecation notice next month, that is now my problem. As a solo dev I do not have the bandwidth to absorb other people's roadmap decisions on top of Apple's. Apple already gives me one platform whose roadmap I do not control. Adding a second is a tax I cannot afford to pay quietly.

There is also a debugging argument that I underrated until I lived it. When an iOS 17.x point release changed the behavior of MFMailComposeViewController on dismissal in a way that left my view controller stack in a strange state, I needed about 40 minutes with the debugger to figure out what had changed. If that flow had been mediated by a third-party "mailer" library, my best case would have been waiting for the maintainer to ship a fix, and my worst case would have been forking, patching, vendoring, and learning a codebase I had spent months pretending I did not need to read.

Zero dependencies, in this framing, is a debuggability decision. Every stack frame is mine. Every breakpoint lands in code I wrote and remember. The first time I hit a real production weirdness and the trace was entirely my own code, I noticed how much faster my brain moved. There was no library to be intimidated by.

What I'd do differently next time (counter-take)

I want to be honest about where this approach is wrong, because I have read enough "zero dependencies" essays to know they tend to be smug.

Three places I was wrong:

First, I was wrong about Sentry-style crash reporting. For a year I leaned on "if it crashes on launch, my few beta testers will tell me." That is fine at a few hundred users. It is not fine if I ever cross a few thousand. I will add a thin crash-reporting integration before any real marketing push, and I will accept that the "zero" in my rule becomes "one" the moment the product has scale.

Second, I was wrong to extend the rule to my server tooling. I run a tiny landing page on a small VPS. I spent a weekend writing my own static-site generator because of the rule. The site is fine. The weekend was wasted. The right answer was Hugo. The rule, I now think, applies cleanly to the shipping app and is mostly noise everywhere else.

Third, I underestimated the cost of "I'll write it myself" in the analytics layer. I have no third-party analytics. I have a single anonymous keepalive ping per app launch and a self-hosted PostHog instance I never finished setting up. I should either commit to running PostHog properly or pick a privacy-friendly hosted analytics product. Pretending the problem does not exist is not a strategy.

The honest version of the rule, after twelve months, is closer to: zero third-party dependencies inside the binary the user installs, while remaining boring and pragmatic about everything outside it.

Takeaways for other solo devs

If you are considering this for your own project, here is what I would do:

  • Run the gate at the moment you reach for any library, not after you have already typed import. The decision is cheap before it is in your code and expensive afterward.
  • Time-box the replacement. If your "I could write this myself" estimate is over one weekend, the library probably earns its place.
  • Write a one-paragraph block in your project README that names every dependency and the reason it survived the gate. Future-you needs the receipts.
  • Measure binary size and cold start before and after each library decision. Numbers protect you from your own taste.
  • Do not extend the rule to tools that never touch the user's device. Static-site generators, build scripts, and CI runners are not part of the product.

Open question for the comments

I am curious what other solo devs do here. Have you tried a zero-dependency rule on a shipping app, and did it survive contact with a real feature? Or did you have the opposite experience, a single well-chosen library that paid for itself ten times over?

What was the last third-party dependency you removed, and what did you replace it with?


I'm a solo dev building Captio-style Simple Memo, an iOS app that emails the note you just typed in about 0.3 seconds. I write here every few days about the messy parts of shipping things alone.