The second time you write similar code, the urge to abstract is strong. Resist it. Two use cases aren't enough to know what the abstraction should be, you end up with a generic layer that fits neither case well.
Wait for the third. By then the pattern is visible: what's shared, what's incidental, what the abstraction should own. The code tells you what it wants to be if you let it repeat once more.
Small systems suffer most from premature abstraction, a records app doesn't need a plugin architecture. Duplication is cheaper than the wrong abstraction, every time.