Swift Developer interview questions
100 real questions with model answers and explanations for Senior Swift Engineer candidates.
See a Swift Developer resume example →Practice with flashcards
Spaced repetition · Hunter Pass
Questions
I would make PricingDomain a Foundation-light package with pure value inputs and deterministic outputs.
- Keep HTTP, persistence, clocks, locale, and UI behind small adapter protocols outside the domain target.
- Represent money as integer minor units and inject the rounding policy so all four executables pass the same golden vectors.
- Publish one versioned fixture suite with 10,000 cases and require every platform job to produce byte-identical results.
Why interviewers ask this: This tests whether the candidate can preserve one domain model across Apple and Linux runtimes without leaking platform concerns.
I would split stable domain types from a LocationPolicy capability supplied by platform adapter targets.
- OrderCore owns coordinates as plain numeric values and never imports CoreLocation.
- AppleLocationAdapter maps CLLocation into the domain type, while LinuxLocationAdapter uses the server geocoder result.
- Only Package.swift and two composition roots know the platform choice, which keeps the 60 domain files portable.
Why interviewers ask this: This evaluates whether platform variance is isolated at explicit composition boundaries rather than hidden behind pervasive compiler flags.
I would version the decision input, rule set, and output as immutable domain values and keep side effects in orchestration layers.
- Each decision records ruleSetVersion, normalized inputs, and an injected timestamp instead of reading globals.
- Current executables contain supported versioned rule data or modules selected at runtime because SwiftPM cannot select a historical package version dynamically within one resolved graph.
- For exact seven-year replay, the CLI streams bounded batches through the archived binary or container for that rule version, verified by cross-platform contract fixtures.
Why interviewers ask this: This checks whether the architecture supports long-lived deterministic replay instead of only current-state execution.
I would organize targets around cohesive capabilities and enforce a shallow, acyclic graph with measured build boundaries.
- Generate the target graph in CI and reject feature-to-feature edges or cycles.
- Separate stable interfaces from heavy implementations only where parallel builds or ownership justify the extra target.
- Use build timing data to collapse tiny targets and split the three targets dominating compilation, then track p95 clean and incremental times.
Why interviewers ask this: This tests whether modularization is driven by ownership and build evidence rather than target count.
I would give each capability an owned public contract and compose implementations only in the application or service root.
- Checkout depends on PaymentsAPI and InventoryAPI targets, never their concrete clients or database models.
- Each API target has one owning team, compatibility tests, and a documented deprecation window of two minor releases.
- Composition roots select live, preview, and test implementations, so feature teams can ship without editing shared singletons.
Why interviewers ask this: This evaluates whether team autonomy is reflected in compile-time dependencies and release contracts.
I would remove the high-fan-out implementation dependency before introducing another build system.
- Use the Swift driver dependency graph and build timeline to confirm which public declarations invalidate downstream modules.
- Move volatile helpers behind a narrow stable target or duplicate a five-line helper when coupling costs more than reuse.
- Set a CI regression gate at 105 seconds and compare ten warmed incremental builds to avoid optimizing noise.
Why interviewers ask this: This tests whether the candidate treats build performance as an architectural dependency problem with measurable limits.
I would keep the public surface small, additive, and built from stable value types rather than exposing implementation frameworks.
- Mark only deliberate declarations public and hide networking, persistence, and generated models behind SDK-owned types.
- Add parameters through overloads or configuration values with defaults, and deprecate old entry points for at least two minor releases.
- Compile representative client fixtures against the new package and run API-diff checks before publishing.
Why interviewers ask this: This tests practical source compatibility and public-surface discipline for a widely consumed Swift library.
I would enable library evolution for the binary boundary and avoid promising layout or exhaustive enum knowledge to clients.
- Build with BUILD_LIBRARY_FOR_DISTRIBUTION and distribute a verified XCFramework plus matching module interfaces.
- Use nonfrozen public structs and enums so stored properties and cases can evolve without breaking old binaries.
- Run old-client/new-library compatibility tests on every weekly candidate and retain the previous artifact for immediate rollback.
Why interviewers ask this: This evaluates understanding of ABI stability, library resilience, and the operational cost of binary distribution.
I would ship a safe replacement additively, measure adoption, and reserve removal for the next major release.
- Deprecate the old symbol with a migration message and keep behavior intact through the current major line.
- Publish a migration guide and test both APIs against the same 25 contract cases to prevent semantic drift.
- Track repository adoption, cut release candidates for the major, and remove only after the six-month window and partner sign-off.
Why interviewers ask this: This tests whether SemVer is handled as a consumer migration contract rather than a version-number convention.
I would keep generics inside the hot typed path and use an existential only at the heterogeneous registration boundary.
- Generic decode and validation preserve static types and specialization for the 8,000-request-per-second path.
- The router registry stores any RouteHandler because it must hold 12 unrelated handlers in one collection.
- Benchmark existential dispatch and allocations on Linux, and add type erasure explicitly if associated types leak into public callers.
Why interviewers ask this: This evaluates whether abstraction choices account for both API ergonomics and measured runtime boundaries.
I would retain specialization only for the measured hot operations and erase types at colder stage boundaries.
- Profile production-sized images to identify the two stages responsible for most CPU, rather than specializing every combinator.
- Expose a non-generic pipeline facade so downstream modules do not instantiate 50 complete generic chains.
- Accept a small dispatch cost outside the hot loop and enforce both CPU and compile-time budgets in CI.
Why interviewers ask this: This checks whether the candidate balances generic specialization against code size and compilation cost.
I would use copy-on-write storage with a uniquely referenced buffer and keep mutation behind a narrow value API.
- The public Batch remains a struct, while an internal final Storage class owns the contiguous records.
- Each mutating operation checks uniqueness before copying, so read-only passage through six stages shares the 20 MB buffer.
- Benchmarks cover shared mutation, peak RSS, and concurrency because accidental reference escape would violate value behavior.
Why interviewers ask this: This tests deep understanding of value semantics, CoW mechanics, and the memory behavior of large data.
I would model immutable workflow states as values and place evolving identity inside one isolated reference owner.
- State snapshots as structs make transitions auditable, comparable, and safe to persist or send across tasks.
- An actor owns the workflow ID and serializes transitions, avoiding shared mutable class graphs.
- Commands include expectedVersion, so stale UI edits fail explicitly rather than overwriting one of 30 transitions.
Why interviewers ask this: This evaluates a nuanced value-versus-reference decision under identity, concurrency, and persistence constraints.
I would add a new capability without immediately making all 25 conformers satisfy a new hard requirement.
- Introduce a refined AuthorizedHandler protocol or an additive method with a safe default only if that default is semantically valid.
- Adapt old conformers at the registry boundary and emit metrics showing which implementations still use legacy behavior.
- Deprecate the old path for two minor releases, then make the requirement mandatory in the next major version.
Why interviewers ask this: This tests protocol evolution that preserves source compatibility without hiding unsafe behavior in defaults.
I would use a peer or member macro only for deterministic declaration generation, while keeping validation semantics in a normal tested library.
- The macro expands explicit fields and diagnostics, but it does not perform network access or depend on developer-machine state.
- Snapshot expansion tests cover 40 representative models and compile-fail tests verify useful diagnostics.
- Adoption starts in one package, with build-time and source-debugging budgets measured before all 300 models migrate.
Why interviewers ask this: This evaluates whether macros reduce repetition without concealing business logic or destabilizing builds.
I would pin source dependencies to reviewed versions or revisions, verify binary artifacts by checksum, and run the plugin in isolated CI.
- Resolve source packages from an approved mirror at an exact version or revision; record a checksum only for a binary artifact where applicable.
- Declare schemas and outputs for build tracking, but use an OS sandbox or isolated container to restrict filesystem and network access because declarations are not read allowlists.
- Give the job no unnecessary secrets, review generated diffs, regenerate from scratch, and record the pinned generator in the release SBOM.
Why interviewers ask this: This checks whether build extensibility is treated as executable supply-chain code rather than a harmless convenience.
I would partition actors by ownership and contention domain rather than place all mutable state in one global actor.
- Account actors serialize one account each, while a sharded cache uses 64 actors selected by stable key hashing.
- Audit writes flow through a bounded batching actor that flushes every 100 ms or 500 records.
- Metrics expose mailbox delay and operation duration per actor so isolation does not hide overload.
Why interviewers ask this: This tests actor topology design for throughput, ownership, and observability at real concurrency.
I would give each document job exclusive ownership of mutable buffers and exchange immutable stage results between regions.
- A per-document actor owns parse state and never shares its mutable byte buffer with another task.
- CPU-bound indexing uses task-group children over immutable chunks capped to the core count.
- Export receives a Sendable snapshot, so cancellation can discard one job without corrupting another document.
Why interviewers ask this: This evaluates whether isolation is designed around data ownership rather than sprinkled actor annotations.
I would make transport messages immutable Sendable values and audit ownership against the exact Apple SDK and SwiftNIO versions in use.
- Modern URLSession is @unchecked Sendable and current NIO releases include audited conformances, so I would not classify either framework wholesale as non-Sendable.
- Keep event-loop-bound resources on their owning loop, document transfer of 5 MB Data values, and wrap only concrete types whose mutable ownership still needs isolation.
- Use @unchecked Sendable only for a narrowly audited wrapper with synchronization and stress tests, never to silence broad warnings.
Why interviewers ask this: This checks whether Sendable conformance expresses real ownership across different runtime adapters.
I would use a bounded task group whose children always return a ShardOutcome, then apply the partial-result policy after aggregation.
- Start at most six shard requests at once to protect connection pools, adding work as children finish.
- Each child catches its own error or 120 ms timeout and returns success or failure metadata, so shard errors cannot escape the group and discard partial results.
- Cancel remaining work at the 180 ms request deadline, aggregate all completed outcomes, and fail only if fewer than eight shards succeeded.
Why interviewers ask this: This evaluates structured concurrency, bounded parallelism, and product-specific failure semantics.
Locked questions
- 21
A media export can run for 20 minutes and spawns 40 child tasks. What cancellation contract would you design for app, server, and CLI callers?
designresilience - 22
A log ingestion pipeline receives 50,000 events per second but storage sustains 30,000. How would you express backpressure with Swift concurrency?
concurrencyswiftbackpressure - 23
A legacy C callback API completes once on a private queue and has a 5-second timeout. How would you expose it as async without leaks or hangs?
asynccallbacksdata-structures - 24
An Objective-C delegate emits 2,000 sensor updates per second and can call back after stop. How would you bridge it into Swift concurrency?
concurrencyswiftprotocols - 25
A sync engine creates tasks that may outlive a screen by 30 seconds and uses a delegate for progress. How would you define ARC ownership?
ownershipdelegationprotocols - 26
A Codable event is stored by Linux services and read by app versions up to 18 months old. How would you evolve the shared contract?
codableserialization - 27
Four Swift clients and a Vapor service share a 120-endpoint contract that changes weekly. Would you generate models or hand-maintain them?
swiftendpointsserver-side - 28
You are designing a Vapor API for 15,000 requests per second, 99.95% availability, and three independently owned domains. What service shape would you choose?
designserver-sideapi - 29
A Vapor endpoint performs 20 ms of CPU parsing and two database calls under a p99 target of 120 ms. How would you protect NIO event loops?
databaseendpointsevent-loop - 30
A multi-tenant Vapor service handles 6,000 concurrent requests, and no mutable request context may cross tenants. How would you isolate request state?
multi-tenancyserver-sideconcurrency - 31
A Vapor service has 120 database connections and traffic spikes to 4,000 requests per second. How would you size Fluent concurrency and pools?
databaseconcurrencyserver-side - 32
Creating an order touches inventory, payment intent, and an audit row, with a 300 ms SLA. Where would you draw Fluent transaction boundaries?
transactions - 33
A public Vapor API serves 3 million users and internal operators with stronger privileges. How would you structure authentication and authorization?
authswiftvalue-types - 34
An API must enforce 100 requests per minute per user across 20 Vapor instances, while allowing a 10-request burst. What limiter would you design?
designserver-sideapi - 35
A mobile client may retry order creation for 24 hours over unreliable networks, and the service handles 2,000 orders per second. How would you guarantee idempotency?
resilienceidempotency - 36
A Vapor endpoint streams 8 GB exports to 500 concurrent clients with a 256 MB memory limit per instance. How would you design it?
designserver-sideendpoints - 37
A collaboration service maintains 80,000 WebSocket connections and broadcasts documents to rooms of up to 2,000 users. What Swift architecture would you use?
swiftwebsocketsarchitecture - 38
A Vapor deployment gets 30 seconds to terminate while requests last up to 10 seconds and background jobs up to 2 minutes. How would you implement graceful shutdown?
lifecyclejobsserver-side - 39
A Linux Swift service has a 99.9% SLO and 150 ms p99 target across 60 endpoints. What observability contract would you build into shared packages?
swiftendpointsobservability - 40
A Swift CLI transforms 1 TB overnight on 200 hosts, and operators need to resume failed runs. What observability would you expose?
swiftobservability - 41
A package must support macOS and Ubuntu for 5 years, but currently imports Darwin and assumes case-insensitive paths. How would you make portability enforceable?
- 42
A SwiftUI trading screen receives 500 price updates per second, while the same domain package powers a CLI. Where would you place state boundaries?
swiftuiswift - 43
A UIKit editor is embedded in a SwiftUI app used by 4 million users, and both frameworks currently own the document state. How would you remove the dual ownership?
uikitswiftuiswift - 44
A cross-platform Swift platform has 600 tests but still ships contract failures monthly. What test pyramid would you establish?
pyramidswift - 45
A Swift SDK and Vapor backend release independently, with 10 supported client versions and weekly schema changes. How would you build contract testing?
contractswiftschema - 46
An actor-based ledger must preserve ordering under 5,000 concurrent test operations. How would you test it without sleeps?
concurrency - 47
A package supports Swift 5.10 and Swift 6 on macOS and Ubuntu, plus two iOS deployment targets, and CI must finish in 18 minutes. What matrix would you run?
swiftdeployment - 48
Eight teams lose 35 engineer-hours daily to Swift builds. How would you prioritize build-performance work over one quarter?
swiftperformanceprioritization - 49
A Swift package handles OAuth tokens for 6 apps and 3 Linux services, and a compromised dependency must not expose them. How would you design the security boundary?
oauthtokensdependencies - 50
A public Swift SDK parses untrusted 25 MB archives on client devices and Linux workers. What safeguards belong in the architecture?
swiftarchitecture - 51
During Swift 6 strict-concurrency migration, warnings jump from 40 to 2,800 across 70 targets and the release is due in six weeks. How do you stage the migration?
concurrencyswiftmigrations - 52
After enabling strict-concurrency checks and parallel request execution, a Linux service corrupts 0.03% of account balances under 6,000 requests per second, while unit tests pass. How do you diagnose the race?
unitconcurrency - 53
An actor-backed inventory check oversells 17 items during a sale because it awaits pricing between read and write. What evidence confirms reentrancy, and what do you change?
asyncconcurrencyactor-reentrancy - 54
After annotating a telemetry dashboard view model @MainActor, frame drops rise from 1% to 17% and main-thread CPU reaches 91% while decoding 2,400 sensor samples per second. How do you fix it?
concurrencyactor-isolation - 55
A Vapor deploy increases live tasks from 4,000 to 240,000 and memory from 700 MB to 9 GB in eight minutes. What do you inspect first?
server-sidedeploymentmemory - 56
Clients cancel 35% of searches, but database CPU remains 92% for 40 seconds afterward. How do you trace and repair cancellation propagation?
databasetracingresilience - 57
A wrapper around a photo callback hangs 1 in 20,000 requests, always near its 10-second timeout. How do you prove a continuation is never resumed?
resiliencecallbacks - 58
Production crashes with SWIFT TASK CONTINUATION MISUSE at a rate of 2 per 1 million requests after adding timeout support. How do you find the double resume?
swiftstructured-concurrencyresilience - 59
A user-initiated export waits 12 seconds behind background indexing even though its task priority is high. How do you diagnose priority inversion?
indexesstructured-concurrency - 60
An AsyncSequence consumer handles 8,000 messages per second while producers send 25,000, and RSS grows 400 MB per minute. What evidence and fix do you want?
asyncconcurrency - 61
An iOS sync session remains allocated after logout, retaining 600 MB and 18 child tasks. How do you isolate the ARC leak?
memorymemory-leakssessions - 62
A macOS controller and Objective-C delegate survive window closure in 4% of sessions. What cycle do you look for and how do you prove the fix?
closuresprotocolssessions - 63
Processing a 120 MB value-type document suddenly peaks at 1.8 GB after one mutation stage. How do you confirm a CoW regression?
concurrency - 64
Replacing a concrete parser with a generic pipeline lowers runtime CPU 8% but grows the Linux binary from 80 MB to 310 MB and cold start by 900 ms. What do you do?
genericsci-cd - 65
Moving 30 handlers into an any Handler registry raises p99 from 75 to 104 ms and allocations by 38%. How do you decide whether existentials caused it?
registries - 66
Package resolution starts taking 11 minutes and produces different versions on developer machines after adding two dependencies. How do you stabilize it?
dependencies - 67
Two shared packages require incompatible major versions of a logging library, blocking 14 teams. How do you resolve the SPM collision?
loggingswift-package-manager - 68
Incremental builds rise from 70 seconds to 9 minutes after a shared protocol gains one associated type. What evidence guides the fix?
typingprotocols - 69
After a route macro release, CI cache hits fall from 82% to 21%, and 7 of 50 clean builds produce different expansions for the same 180 routes. Do you roll back or repair?
cachingrollback - 70
A build plugin running in 18 repositories unexpectedly connects to the internet, and CI secrets are exposed in its child-process environment for 27 minutes. What is your incident response?
incidentssecretsconcurrency - 71
An XCFramework update crashes only on devices running the oldest supported OS, affecting 6% of users. How do you handle the binary artifact incident?
soft-skillsincidentsartifacts - 72
A backend changes retryAfterSeconds from a JSON number to a String, and 12% of active clients fail Codable decoding. What rollback do you execute?
codableserializationresilience - 73
A new enum case from the server causes 80,000 daily CLI jobs to exit before processing. How do you recover without hiding semantic errors?
concurrencyenums - 74
A Vapor endpoint p99 jumps from 90 ms to 4.2 seconds, and event-loop lag is 1.8 seconds after adding PDF parsing. What do you do in the first 15 minutes?
server-sideendpoints - 75
After a deploy, service p99 doubles from 140 to 290 ms while CPU, memory, and error rate remain flat. How do you narrow the cause?
memorydeployment - 76
One NIO event loop shows 95% utilization while seven remain below 25%, and only long-lived connections are slow. What do you investigate?
event-loop - 77
A list endpoint grows from 12 to 1,201 SQL queries and p99 reaches 2.6 seconds for 100 records. How do you confirm and fix Fluent N+1?
sqln+1queries - 78
Fluent pool acquisition p95 rises to 3 seconds, 18% of requests time out, but PostgreSQL uses only 35% CPU. What do you inspect?
postgres - 79
Two Fluent transactions deadlock 40 times per hour after a batch feature launches. How do you identify and remove the cycle?
transactionslockingbatch - 80
A Fluent migration adding an index locks a 400-million-row table and write latency exceeds 30 seconds. What is your recovery and safer plan?
indexesmigrationslatency - 81
After an auth-cache optimization, 23 requests return data from the wrong tenant in one hour. How do you contain and diagnose it?
cachingoptimization - 82
A payment endpoint creates 31 duplicate charges during a 20-minute network incident despite idempotency keys. Where do you look?
endpointsidempotencyincidents - 83
A global rate limiter should allow 5,000 requests per second but admits 8,700 during Redis failover. How do you redesign degraded behavior?
redisrate-limiting - 84
A WebSocket room with 2,000 members causes one event to consume 1.4 CPU-seconds and fanout latency reaches 9 seconds. How do you respond?
latencywebsockets - 85
Five percent of WebSocket clients consume 20 times slower, and per-connection queues grow until instances restart. What policy do you implement?
websocketsdata-structures - 86
A Linux Swift service is OOM-killed at 12 GB every six hours while heap snapshots show no single dominant leak. How do you investigate?
data-structuresswiftsnapshot - 87
During deployment, 2% of in-flight uploads truncate because instances exit 14 seconds after SIGTERM. How do you repair graceful shutdown?
lifecycledeployment - 88
A Swift CLI sorting a 300 GB file reaches 64 GB RSS and is killed halfway through. What redesign and evidence do you require?
algorithmsswift - 89
A CLI receives SIGINT during a 40-minute import, exits after 90 seconds, and leaves 12 child processes. How do you fix signal handling?
concurrency - 90
A formatter CLI is interrupted while replacing 18,000 files and leaves 73 zero-byte files. How do you eliminate partial-file corruption?
- 91
A SwiftUI dashboard redraws 4,500 rows on every one-second tick and energy use doubles. How do you isolate the invalidation source?
swiftuiswift - 92
Embedding a UIKit editor in SwiftUI duplicates save commands in 0.4% of sessions after navigation. How do you diagnose ownership?
uikitswiftuinavigation - 93
A 900,000-line Objective-C product must move networking to Swift without changing behavior for 8 million users. What incremental sequence do you choose?
swift - 94
You must enable strict concurrency in a 45-target package while three teams ship weekly and cannot pause feature work. How do you prevent a flag-day migration?
concurrencyswift-concurrencymigrations - 95
A public library must replace a callback API with async/await while supporting clients for 12 months. How do you migrate without a breaking release?
asynccallbacksconcurrency - 96
In review, an engineer proposes @unchecked Sendable on a mutable cache used by 30 tasks and says tests pass. How do you mentor through the decision?
mentoringcachingtesting - 97
A teammate puts Data(contentsOf:) inside a Vapor route; staging p99 rises from 100 ms to 1.6 seconds with 200 concurrent requests. How do you handle the review and learning?
soft-skillsconcurrencyserver-side - 98
During a pool-exhaustion incident, a junior engineer wants to raise PostgreSQL connections from 120 to 500 immediately. How do you guide the response?
incidentspostgres - 99
A code review adds a debug snapshot that retains every 50 MB CoW buffer for undo, and peak memory becomes 2.4 GB. How do you coach a better design?
code-reviewdesignsnapshot - 100
A team wants to skip Linux integration tests to cut CI from 22 to 14 minutes, after three portability regressions last quarter. How do you lead the review?
integration